{"id":37065581,"url":"https://github.com/superloopnetwork/superloop","last_synced_at":"2026-01-14T07:40:42.963Z","repository":{"id":52764710,"uuid":"141303739","full_name":"superloopnetwork/superloop","owner":"superloopnetwork","description":"Superloop is a network automation framework, used to manage networks at scale. It's a framework that auto remediates based on templates and maintains config standardization across device platforms. As well, it comes equipped with various toolsets that assist Network Engineers with their day to day tasks.","archived":false,"fork":false,"pushed_at":"2024-10-14T17:16:29.000Z","size":4741,"stargazers_count":14,"open_issues_count":1,"forks_count":7,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-10T20:41:03.426Z","etag":null,"topics":["auditing","automation","cfgs","cisco","configs","f5","ios","jinja2","juniper","junos","pushing","remediation","superloop","tmsh","vyatta"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/superloopnetwork.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":"auditcreeper.py","citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-07-17T14:47:39.000Z","updated_at":"2024-11-05T19:34:09.000Z","dependencies_parsed_at":"2023-12-09T21:25:36.552Z","dependency_job_id":"c38797b9-abc2-4a2d-b122-bf9be10ad0a7","html_url":"https://github.com/superloopnetwork/superloop","commit_stats":{"total_commits":556,"total_committers":3,"mean_commits":"185.33333333333334","dds":"0.0053956834532373765","last_synced_commit":"c2e45354de4bb78ff581e08a04bababb11ba1d2a"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/superloopnetwork/superloop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/superloopnetwork%2Fsuperloop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/superloopnetwork%2Fsuperloop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/superloopnetwork%2Fsuperloop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/superloopnetwork%2Fsuperloop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/superloopnetwork","download_url":"https://codeload.github.com/superloopnetwork/superloop/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/superloopnetwork%2Fsuperloop/sbom","scorecard":{"id":859631,"data":{"date":"2025-08-11","repo":{"name":"github.com/superloopnetwork/superloop","commit":"996fd08a4381b5d6b95e47d75bdfbadfc3bdae6c"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.3,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/28 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 4 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"12 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-3ww4-gg4f-jr7f","Warn: Project is vulnerable to: GHSA-5cpq-8wj7-hf2v","Warn: Project is vulnerable to: GHSA-9v9h-cgj8-h64p","Warn: Project is vulnerable to: PYSEC-2023-254 / GHSA-jfhm-5ghh-2f97","Warn: Project is vulnerable to: GHSA-jm77-qphf-c4w8","Warn: Project is vulnerable to: GHSA-v8gr-m533-ghj9","Warn: Project is vulnerable to: GHSA-w7pp-m8wf-vj6r","Warn: Project is vulnerable to: GHSA-x4qr-2fvf-3mr5","Warn: Project is vulnerable to: GHSA-cpwx-vrp4-4pq7","Warn: Project is vulnerable to: GHSA-h5c8-rqwp-cp95","Warn: Project is vulnerable to: GHSA-h75v-3vvj-5mfj","Warn: Project is vulnerable to: GHSA-q2x7-8rv6-6q7h"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-24T00:52:36.491Z","repository_id":52764710,"created_at":"2025-08-24T00:52:36.491Z","updated_at":"2025-08-24T00:52:36.491Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28413470,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T05:26:33.345Z","status":"ssl_error","status_checked_at":"2026-01-14T05:21:57.251Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["auditing","automation","cfgs","cisco","configs","f5","ios","jinja2","juniper","junos","pushing","remediation","superloop","tmsh","vyatta"],"created_at":"2026-01-14T07:40:42.352Z","updated_at":"2026-01-14T07:40:42.949Z","avatar_url":"https://github.com/superloopnetwork.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# superloop\nInspired by the world's leading social media tech company (Facebook) for network automation, I have created my own version of the framework.\n\n## Prerequisites\n  1. Python 3.6 or higher.\n  2. netmiko - A HUGE thanks and shout out to Kirk Byers for developing the library!\n  3. snmp_helper.py - module written by Kirk Byers (https://github.com/ktbyers/pynet/blob/master/snmp/snmp_helper.py).\n  4. ciscoconfparse - A library to help parse out Cisco (or similiar) CLI configs (https://pypi.org/project/ciscoconfparse/).\n  5. yaml - YAML is a human-readable data-serialization language (https://en.wikipedia.org/wiki/YAML).\n  6. libyaml-cpp-dev - C parser for yaml (xargs apt-get install \u003c requirements.apt)\n  7. jinja2 - template engine for Python (https://jinja.palletsprojects.com/en/2.11.x/)\n  8. hvac - Python client for hashicorp vault (https://pypi.org/project/hvac/).\n\n## Support\n\n|__Platform__|__audit diff__|__push cfgs__|__host exec__|__ssh__ |__node list__|__host add__|__host remove__|__host discover__|__push acl__|__pull cfgs__|\n|------------|:------------:|:-----------:|:-----------:|:------:|:-----------:|:----------:|:-------------:|:---------------:|:----------:|:------------|\n| Cisco IOS  |       x      |      x      |       x     |    x   |      x      |      x     |       x       |        x        |      -     |      x      |\n| Cisco NXOS |       x      |      x      |       x     |    x   |      x      |      x     |       x       |        x        |      -     |      x      |\n| Cisco ASA  |       x      |      x      |       x     |    x   |      x      |      x     |       x       |        x        |            |      x      |\n| Juniper OS |       x      |      x      |       x     |    x   |      x      |      x     |       x       |        x        |            |      x      |\n|F5 BigIP LTM|       x      |      x      |       x     |    x   |      x      |      x     |       x       |        x        |      -     |      x      |\n|  Netscaler |       x      |      x      |       x     |    x   |      x      |      x     |       x       |        x        |      -     |      x      |\n\n## Overview\n\n![superloop gitops_operational_framework](https://github.com/superloopnetwork/superloop/blob/master/gifs/superloop_gitops_operational_framework.png)\n\n\n## Install\n\nThere are a few methods to install superloop but the easiest is the following:\n\nAn appropriate install location would be in ```/usr/local/```\n\n```\n   $ cd /usr/local/\n   $ git clone https://github.com/superloopnetwork/superloop\n   $ cd superloop/\n   $ pip3 install -r requirements.txt\n   $ xargs apt-get install \u003c requirements.apt\n```\n\nThis will install superloop along with all required dependencies to the directory. \n\nIMPORTANT: To simplify the execution of superloop application, please do the following after installation.\n\nCreate a symbolic link of 'superloop.py' and place it in '/usr/local/bin/'. Set the permission to 755. (replace python3.x with your correct python version)\n```\n$ ln -s /usr/local/superloop/superloop.py /usr/local/bin/superloop\n$ chmod 755 /usr/local/bin/superloop\n```\nNow uncomment the following code within ```/usr/local/bin/superloop``` near the top:\n```\n#import sys\n#sys.path.append('/usr/local/superloop')\n```\nSo it looks like this . . . . \n```\n#!/usr/bin/python3\nimport sys\nsys.path.append('/usr/local/superloop')\nfrom auditdiff import auditdiff\nfrom push_cfgs import push_cfgs\n...\n..\n.\n\u003coutput truncated\u003e\n```\nThis will set the system path of superloop to '/usr/local/superloop'. If you have superloop installed in another directory, change the path accordingly (replace python3.x with appropriate version).\n\nIn Netmiko version 3.x by default is going to expect the configuration command to be echoed to the screen. This ensures Netmiko doesn't get out of sync with the underlying device (ex. keep sending configuration commands even though the remote device might be too slow and buffering them).\n\nWe will need to turn off command verification in netmiko base_connection.py file:\n```\nvi /usr/local/lib/python3.7/dist-packages/netmiko/base_connection.py\n```\nSearch for the function 'send_config_set' and change 'cmd_verify=True' to 'cmd_verify=False' like this:\n```\n    def send_config_set(\n        self,\n        config_commands=None,\n        exit_config_mode=True,\n        delay_factor=1,\n        max_loops=150,\n        strip_prompt=False,\n        strip_command=False,\n        config_mode_command=None,\n        cmd_verify=False,\n        enter_config_mode=True,\n    ):\n```\nWe also need to disable `enqueue` in ciscoconfparse package (dependancy of loguru package) as this stalls/hangs/locks threading in superloop.\n```\nvi /usr/local/lib/python3.7/dist-packages/ciscoconfparse/ccp_util.py\n```\nSearch for `enqueue=True,` and change it to `enqueue=False,'\n\nBefore we begin, I've constructed this application for easy database management by utilizing the power of YAML files. There are a combination of two YAML files that require management (default path is ~/database/):\n\n  1. nodes.yaml\n  2. templates.yaml\n\nThe nodes.yaml holds all inventory of devices in the network. The templates.yaml file are mappings of templates so superloop knows which template is provisioned. The state of each template is appended at the end of the mapping to either 'disabled' or 'enabled' pushing of template. This acts as a safety feature. Zero to low confidence templates should never be pushed in a production environment as it may cause impact. However, all templates can be audited or rendered as there is no impact involved; this does not require the state of the template(s) to be flipped to 'enabled'\n```\nroot@devvm:~# cat superloop_code/database/templates.yaml\n---\n- hardware_vendor: cisco \n  type: firewall\n  opersys: asa \n  templates:\n  - ~/superloop_code/templates/hardware_vendors/cisco/asa/firewall/base.jinja2: disabled\n  - ~/superloop_code/templates/hardware_vendors/cisco/asa/firewall/object-groups.jinja2: disabled\n  - ~/superloop_code/templates/hardware_vendors/cisco/asa/firewall/logging.jinja2: enabled\n- hardware_vendor: cisco\n  type: router \n  opersys: ios\n  templates:\n  - ~/superloop_code/templates/hardware_vendors/cisco/ios/router/base.jinja2: enabled\n- hardware_vendor: cisco\n  type: switch \n  opersys: ios \n  templates:\n  - ~/superloop_code/templates/hardware_vendors/cisco/ios/switch/base.jinja2: disabled\n  - ~/superloop_code/templates/hardware_vendors/cisco/ios/switch/logging.jinja2: enabled\n  - ~/superloop_code/templates/hardware_vendors/cisco/ios/switch/service.jinja2: disabled\n  - ~/superloop_code/templates/hardware_vendors/cisco/ios/switch/dhcp.jinja2: enabled\n  - ~/superloop_code/templates/hardware_vendors/cisco/ios/switch/snmp.jinja2: enabled\n  - ~/superloop_code/templates/hardware_vendors/cisco/ios/switch/interfaces.jinja2: disabled\n- hardware_vendor: juniper\n  type: vfirewall\n  opersys: junos\n  templates:\n  - ~/superloop_code/templates/hardware_vendors/juniper/junos/vfirewall/routing-instances.jinja2: disabled\n  - ~/superloop_code/templates/hardware_vendors/juniper/junos/vfirewall/routing-options.jinja2: disabled\n  - ~/superloop_code/templates/hardware_vendors/juniper/junos/vfirewall/system.jinja2: enabled\n  - ~/superloop_code/templates/hardware_vendors/juniper/junos/vfirewall/interfaces.jinja2: disabled\n  - ~/superloop_code/templates/hardware_vendors/juniper/junos/vfirewall/protocols.jinja2: disabled\n- hardware_vendor: synology \n  type: nas\n  opersys: busybox\n  templates:\n  - ~/superloop_code/templates/hardware_vendors/synology/busybox/base.jinja2: enabled\n  ```\n\n## Credentials\n\nCredentials used to connect to nodes are via the OS environment varilable, $USER. It will prompt you for your password\n```\nexport USERNAME=username\n```\n\n## Hierarchy\n\nYou'll noticed the superloo_code/ and superloop/ source code are completely segregated by different repositories. superloop_code/ repo can be found here and should be cloned to the home directory of the user as that is where superloop references to. Hourly backups should be stored in the superloop_code/backup-configs directory via CI/CD. superloop_code/database are where the inventory of the devices, templates (reference) files are stored. superloop_code/templates are where all the templates are stored. The hierarchy is structured based on vendor, OS and device type when it comes to templates. That's because different vendors and OS have different syntaxes. ex. Cisco IOS have different syntaxes than Cisco NXOS.\n```\nroot@devvm:~# tree superloop_code/\nsuperloop_code/\n├── database\n│   ├── nodes.yaml\n│   ├── policies.yaml\n│   ├── templates.yaml\n│   └── templates.yaml.bak\n├── policy\n│   ├── APPLICATIONS.net\n│   ├── cisco\n│   │   └── ios\n│   │       └── firewall\n│   │           └── base_policy.json\n│   ├── juniper\n│   │   └── junos\n│   │       └── vfirewall\n│   │           └── policy.json\n│   ├── NETWORKS.net\n│   ├── SERVICES.net\n│   ├── SOURCE_DEVICE.net\n│   ├── SOURCE_USER.net\n│   ├── :w\n│   └── ZONES.net\n└── templates\n    ├── hardware_vendors\n    │   ├── cisco\n    │   │   ├── asa\n    │   │   │   └── firewall\n    │   │   │       ├── base.jinja2\n    │   │   │       ├── logging.jinja2\n    │   │   │       ├── object-groups.jinja2\n    │   │   │       └── snmp.jinja2\n    │   │   ├── ios\n    │   │   │   ├── router\n    │   │   │   │   └── base.jinja2\n    │   │   │   └── switch\n    │   │   │       ├── aaa.jinja2\n    │   │   │       ├── base.jinja2\n    │   │   │       ├── base.jinja2.bak\n    │   │   │       ├── crypto.jinja2\n    │   │   │       ├── cs_vserver.jinja2\n    │   │   │       ├── dhcp.jinja2\n    │   │   │       ├── interfaces.jinja2\n    │   │   │       ├── logging.jinja2\n    │   │   │       ├── service.jinja2\n    │   │   │       └── snmp.jinja2\n    │   │   └── nxos\n    │   ├── f5\n    │   │   └── bigip\n    │   └── juniper\n    │       └── junos\n    │           └── vfirewall\n    │               ├── interfaces.jinja2\n    │               ├── protocols.jinja2\n    │               ├── routing-instances.jinja2\n    │               ├── routing-options.jinja2\n    │               └── system.jinja2\n    └── standards\n        └── common.jinja2\n\n```\nLet's look at a simple Cisco platform_name jinja2 template as an example.\n\n```\n{# audit_filter = ['snmp-server (?!user).*'] #}\n{%- import 'global.jinja2' as global -%}\n{%- import 'datacenter.jinja2' as dc -%}\n{%- import 'environment.jinja2' as env -%}\n{# %- import node.name ~ '.jinja2' as device -% #}\nsnmp-server community {{ secrets['community_1'] }} group network-operator\nsnmp-server community {{ secrets['community_2'] }} group network-operator\nsnmp-server community {{ secrets['community_3'] }} group network-operator\nsnmp-server location {{ dc.snmp.location }}\n```\nNotice there is a section called 'audit_filter' at the top of file. This audit filter should be included in all templates of Cisco and Citrix Netscaler. It accepts a regular expression. This tells superloop which lines to look for and compare against when rendering the configs. In other words, superloop will look for only lines that begin with 'snmp-server' and anything else trailing but exclude 'user' as the second piece of string. If you have additional lines that you want superloop to look at, simply append strings seperated by a comma like so...\n```\n['snmp-server (?!user).*','hello','world']\n```\nThere are a few import statements that you may need to include depending on the variables you need to use. The files are organized based on the logic and reference to their geographic location.\n\nglobal.jinja2 maps to ~/superloop_code/templates/standards/global.jinja2 # all global variables will stored in this file.\n\ndatacenter.jinja2 maps to ~/superloop_code/templates/datacenter/\u003csite_name\u003e/datacenter.jinja2 # all variables pertaining to datacenter/region specific will be stored in this file.\n\nenvironment.jinja2 maps to ~/superloop_code/templates/datacenter/\u003csite_name\u003e/prod/environment.jinja2 # all variables pertaining to the different region and environment will be stored in this file.\n\nNEVER include any secrets (static) within any templates as they will be exposed in clear text and visible in version control. Instead we want to mask our secrets by storing them in hashicorp and calling them in this fashion:\n```\n{{ secrets['community_1'] }}\n```\nMappings can be found here: Networking \u003e prod \u003e secrets in vault. Every time when a template is being rendered for output, superloop will authenticate with vault. If successful, it then queries the requested secret. The secret is returned to superloop and is then pushed to jinja for output. With this method, no secrets are exposed in any files.\n\nYou may also have a template that consist of one or several levels deep like so...\n```\n{# audit_filter = ['ip dhcp .*'] #}\nip dhcp excluded-address 10.50.80.1\nip dhcp ping packets 5\n!\nip dhcp pool DATA\nnetwork 10.10.20.0 255.255.255.0\ndefault-router 10.10.20.1\ndns-server 8.8.8.8\n```\nLook at 'ip dhcp pool DATA'. The next line of config has an indentation. The parent is considered 'ip dhcp pool DATA' and the child are anything below that section. superloop is intelligent enough to parse the remaining 3 lines of configs without having to include it into the audit_filter.\n\nNow that I have explained the basic operations, onto the fun stuff!\n\n## superloop host add\nWhen you add a device, every attribute of the node will be discovered automatically so there is no need to populate it manually.\n```\nroot@devvm:~# superloop host add 10.202.1.7\n+ SNMP discovery successful.\n+ New node appended to database.\n```\n\n## superloop host remove\nTo remove a node, simply execute a 'superloop host remove \u003cIPv4/hostname\u003e':\n```\nwailit.loi@pc-netauto-001:~$ superloop host remove 10.202.1.7\n- Node successfully removed from database.\n```\n\n## superloop node list\nTo verify the device attributes:\n\n```\nroot@devvm:~# superloop node list pt-switch-001\n[\n    {\n        \"created_at\": \"2022-09-12 14:02:10\"\n        \"created_by\": \"wailit.loi\"\n        \"data\": {\n            \"managed_configs\": {\n                   \"logging.jinja2\"\n                   \"ntp.jinja2\"\n                   \"snmp.jinja2\"\n             }\n         }\n        \"domain_name\": \"null\"\n        \"environment\": \"prod\"\n        \"hardware_vendor\": \"cisco\"\n        \"lifecycle_status\": \"null\"\n        \"location_name\": \"toronto\"\n        \"mgmt_con_ip4\": \"null\"\n        \"mgmt_ip4\": \"10.202.1.7\"\n        \"mgmt_oob_ip4\": \"null\"\n        \"mgmt_snmp_community4\": \"null\"\n        \"name\": \"core1.leaf.yyz.demo.domain.name\"\n        \"opersys\": \"ios\"\n        \"platform_name\": \"WS-C3750X-48\"\n        \"role_name\": \"datacenter-switch\"\n        \"serial_num\": \"FDO1629R0JL\"\n        \"software_image\": \"null\"\n        \"software_version\": \"null\"\n        \"status\": \"online\"\n        \"type\": \"switch\"\n        \"updated_at\": \"null\"\n        \"updated_by\": \"null\"\n    }\n]\n```\n\n## superloop host update\n\nNotice the 'name' or hostname of the device has the domain appended because the 'ip domain-name domain.name' is configured. If the domain name is not required, superloop has the ability to modify the database attribute from cli:\n```\nroot@devvm:~#  superloop host update core1.leaf.yyz.domain.name --help\nusage: superloop host update [-h] [-a ATTRIBUTE] [-am AMEND] node\npositional arguments:\n  node\noptional arguments:\n  -h, --help            show this help message and exit\n  -a ATTRIBUTE, --attribute ATTRIBUTE\n                        Specify the attribute that requires updating\n  -am AMEND, --amend AMEND\n                        The value that is being amended\n \nroot@devvm:~# superloop host update core1.leaf.demo.domain.name -a name -am core1.leaf.yyz.demo\nPlease confirm you would like to change the value from core1.leaf.yyz.demo.domain.name : name : core1.leaf.yyz.demo.domain.name to core1.leaf.yyz.demo.domain.name : name : core1.leaf.yyz.demo. [y/N]: y\n+ Amendment to database was successful.\n```\nWe can take a look at the 'node list' feature to verify the 'name' attribute has changed:\n```\nroot@devvm:~# superloop node list core1.leaf.yyz.demo\n[\n    {\n        \"created_at\": \"2022-09-12 14:02:10\"\n        \"created_by\": \"wailit.loi\"\n        \"data\": {\n            \"managed_configs\": {\n                   \"logging.jinja2\"\n                   \"ntp.jinja2\"\n                   \"snmp.jinja2\"\n             }\n         }\n        \"domain_name\": \"null\"\n        \"environment\": \"prod\"\n        \"hardware_vendor\": \"cisco\"\n        \"lifecycle_status\": \"null\"\n        \"location_name\": \"telecity\"\n        \"mgmt_con_ip4\": \"null\"\n        \"mgmt_ip4\": \"10.202.1.7\"\n        \"mgmt_oob_ip4\": \"null\"\n        \"mgmt_snmp_community4\": \"null\"\n        \"name\": \"core1.leaf.yyz.demo\"\n        \"opersys\": \"ios\"\n        \"platform_name\": \"WS-C3750X-48\"\n        \"role_name\": \"datacenter-switch\"\n        \"serial_num\": \"FDO1629R0JL\"\n        \"software_image\": \"null\"\n        \"software_version\": \"null\"\n        \"status\": \"online\"\n        \"type\": \"switch\"\n        \"updated_at\": \"2022-09-12 14:13:36\"\n        \"updated_by\": \"wailit.loi\"\n    }\n]\n```\nWhen it comes to templating, we are able to call these attributes directly and make logical decisions based on the value. We'll discuss more later on in this article...\n\n## superloop push render\nThe 'push render' function, simply renders a template created in jinja2. Ensure the template is provisioned in the ~/superloop_code/database/templates.yaml file so superloop understands which template(s) is/are loaded. If we want to render a template, we simply execute 'superloop push render --node \u003cregex\u003e --file \u003cname_of_template\u003e'. --node accepts a regular expression to match (multiple) node(s) and it can be as granular as you wish. Ex. matching an entire datacenter and/or device type. If there is no '–file' flag supplied, ALL templates for the device specific type will be rendered.\n```\nroot@devvm:~# superloop push render --node core.*sw.*.yyz.*demo --file logging\ncore1.sw.yyz.demo\n/root/superloop_code/templates/hardware_vendors/cisco/nxos/switch/logging.jinja2\nlogging message interface type ethernet description\nlogging logfile messages 6 size 32768\nlogging server 10.100.10.53\nlogging server 10.100.2.40\nlogging timestamp milliseconds\nlogging monitor 3\nno logging rate-limit\n \ncore2.sw.yyz.demo\n/root/superloop_code/templates/hardware_vendors/cisco/nxos/switch/logging.jinja2\nlogging message interface type ethernet description\nlogging logfile messages 6 size 32768\nlogging server 10.100.10.53\nlogging server 10.100.2.40\nlogging timestamp milliseconds\nlogging monitor 3\nno logging rate-limit\n```\n\n## superloop audit diff\nThis function was designed to compare against the jinja2 templates with your running-configurations/candidate-configurations to see if they are according to standards. You could imagine if you had hundreds, if not thousands of devices to maintain, standardization would be a nightmare without some form of auditing/automation tool. To paint you an example, say one day, an employee decides to make an unauthorized manual configuration change on a switch. No one knows about it or what they did. 'superloop' is able to dive into all devices and see if there were any discrepancies against the template as that is considered the trusted source. 'superloop' is then able to determine what was exactly modified or changed. Whatever was configured would essentially be negated automatically. This works the other way around as well. If configuration(s) on a device(s) does not have the standard rendered configs from the template (configs removed), superloop will determine they are missing and you may proceed to remediate by pushing the rendered configs. 'audit diff' will audit against ONE or ALL templates belonging to the matched device(s) from the query. If you want to audit against ONE template, simply include the option '--file \u003ctemplate_name\u003e' (exclude extension .jinja2). If you want to audit against ALL templates belonging to the matched device(s) query, do not include the '--file' option.\n\n```\nroot@devvm:~# superloop audit diff -n pc.*test -f snmp                                   \nPassword:\n[\u003e] complete [0:00:10.911552]\n \nOnly in the device: -\nOnly in the generated config: +\npc-n9ktest-001\n/root/superloop_code/templates/hardware_vendors/cisco/nxos/switch/snmp.jinja2\n- snmp-server community helloworld group network-operator\n+ snmp-server location coresite\n```\n\n## superloop push cfgs\nThe 'push cfgs' function simply pushes the template(s) to the specified node(s). For Cisco, Citrix, F5 and Palo Alto devices, a debug output will be shown with a list of commands (if any) of what will be sent first before user commits to push. From the below example, you can see which templates are enabled for pushing, represented by [\u003e] vs. which templates are disabled, represented by [x]. The state of the template can be controlled in the ~/superloop_code/database/templates.yaml file. As a safety, we disable any templates that we are not confident in pushing. If enabled, superloop will auto remediate those template(s). Please use with caution as it can cause severe impact. Two phases happens when pushing templates of Cisco, Citrix, F5 and Palo Alto devices. First, superloop performs an audit diff. It will check to see what configs are missing or removed. Second, it will encapsulate the necessary configs and prepare it for pushing. If the device has no diffs, then no configs will be pushed to the device. The output of session when pushing will be displayed so users can see what happens behind the scenes.\n\n```\nroot@devvm:~# superloop push cfgs --node p.*nxs\n[x] core1.sw.yyz.demo ; base.jinja2\n[x] core1.sw.yyz.demo ; base.jinja2\n[x] core2.sw.yyz.demo ; base.jinja2\n[x] core2.sw.yyz.demo ; base.jinja2\n[x] core1.leaf.yyz.demo ; base.jinja2\n[x] core2.leaf.yyz.demo ; base.jinja2\n[x] core3.leaf.yyz.demo ; base.jinja2\n[\u003e] core1.sw.yyz.demo ; logging.jinja2\n[\u003e] core1.sw.yyz.demo ; ntp.jinja2\n[\u003e] core1.sw.yyz.demo ; snmp.jinja2\n[\u003e] core1.sw.yyz.demo ; logging.jinja2\n[\u003e] core1.sw.yyz.demo ; ntp.jinja2\n[\u003e] core1.sw.yyz.demo ; snmp.jinja2\n[\u003e] core2.sw.yyz.demo ; logging.jinja2\n[\u003e] core2.sw.yyz.demo ; ntp.jinja2\n[\u003e] core2.sw.yyz.demo ; snmp.jinja2\n[\u003e] core2.sw.yyz.demo ; logging.jinja2\n[\u003e] core2.sw.yyz.demo ; ntp.jinja2\n[\u003e] core2.sw.yyz.demo ; snmp.jinja2\n[\u003e] core1.leaf.yyz.demo ; logging.jinja2\n[\u003e] core1.leaf.yyz.demo ; ntp.jinja2\n[\u003e] core1.leaf.yyz.demo ; snmp.jinja2\n[\u003e] core2.leaf.yyz.demo ; logging.jinja2\n[\u003e] core2.leaf.yyz.demo ; ntp.jinja2\n[\u003e] core2.leaf.yyz.demo ; snmp.jinja2\n[\u003e] core3.leaf.yyz.demo ; logging.jinja2\n[\u003e] core3.leaf.yyz.demo ; ntp.jinja2\n[\u003e] core3.leaf.yyz.demo ; snmp.jinja2\n+ complete [0:00:11.403772]\n \n[DEBUG]\n{\n    \"core2.leaf.yyz.demo\": [\n        [\n            \"ntp logging\"\n        ]\n    ],\n    \"core3.leaf.yyz.demo\": [\n        [\n            \"ntp logging\"\n        ]\n    ]\n}\nconfig term\nEnter configuration commands, one per line. End with CNTL/Z.\n \ncore2.leaf.yyz.demo(config)# ntp logging\n \ncore2.leaf.yyz.demo(config)# end\n \ncore2.leaf.yyz.demo#\nconfig term\nEnter configuration commands, one per line. End with CNTL/Z.\n \ncore3.leaf.yyz.demo(config)# ntp logging\n \ncore3.leaf.yyz.demo(config)# end\n \ncore3.leaf.yyz.demo#\n+ complete [0:00:14.664805]\n```\n\n## superloop push local\n\nThe 'push local' command allows you to push configs that are stored in a text file (home directory). This feature is useful when performing migrations. For example, if we wanted to drain/undrain traffic from one node, we could pre-configure the set of commands in the text file. At the time of migration, we can push the configs to the selected nodes. This method would eliminate any human error in the process.\n\n## superloop ssh\nSSH feature allows us to quickly search up node(s) via regular expression and establish a SSH session with the device. This is useful when you have thousands of nodes in the network and memorizing IP addresses is simply not an option.\n```\nroot@devvm:~# superloop ssh p.*lb.*act\nid                        name                           address                   platform\n1                         core1.lb.yyz.demo.active       10.10.10.1               citrix                  \n2                         core1.lb.sfo.demo.active       10.10.10.2               citrix                  \n3                         core1.lb.sin.demo.active       10.10.10.3               citrix\n```\n## superloop host exec\nThe 'host exec' features allow you to execute a command on the device(s) without requiring you to log in manually one by one. This feature is extremely useful at times when you want to check status across multi devices.\n```\nroot@devvm:~# superloop host exec \"show ip interface brief\" --node core.*sw.*yyz.*demo       \nPassword:\ncore1.sw.yyz.demo: IP Interface Status for VRF \"default\"(1)\ncore1.sw.yyz.demo: Interface            IP Address      Interface Status\ncore1.sw.yyz.demo: Vlan201              10.201.1.22     protocol-up/link-up/admin-up      \ncore1.sw.yyz.demo:\n \ncore2.sw.yyz.demo: IP Interface Status for VRF \"default\"(1)\ncore2.sw.yyz.demo: Interface            IP Address      Interface Status\ncore2.sw.yyz.demo: Vlan201              10.201.1.23     protocol-up/link-up/admin-up      \ncore2.sw.yyz.demo:\n \n[\u003e] Complete [0:00:08.375958]\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsuperloopnetwork%2Fsuperloop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsuperloopnetwork%2Fsuperloop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsuperloopnetwork%2Fsuperloop/lists"}