├── pkgs ├── __init__.py ├── urls.py ├── templates │ └── pkgs │ │ ├── done.html │ │ ├── deleted.html │ │ ├── orphaned.html │ │ ├── confirm.html │ │ └── index.html └── static │ └── js │ └── pkgs.js ├── version ├── catalogs ├── __init__.py ├── templatetags │ ├── __init__.py │ └── catalog_extras.py ├── templates │ └── catalogs │ │ ├── dict_list.html │ │ ├── generic_dict.html │ │ ├── item_detail.html │ │ └── catalog.html ├── static │ ├── css │ │ ├── catalogs.css │ │ └── tapdrop.css │ └── js │ │ ├── catalogs.js │ │ └── bootstrap-tabdrop.js ├── urls.py ├── tests.py ├── models.py └── views.py ├── manifests ├── __init__.py ├── tests.py ├── urls.py └── templates │ └── manifests │ ├── delete.html │ ├── new.html │ ├── index.html │ └── detail.html ├── munkido ├── __init__.py ├── templatetags │ ├── __init__.py │ └── base_extras.py ├── site_static │ ├── less │ │ ├── mixins.less │ │ ├── variables.less │ │ └── sb-admin-2.less │ ├── img │ │ ├── ssh.png │ │ ├── Munki.png │ │ ├── logo.png │ │ ├── arrow-up.gif │ │ ├── favicon.ico │ │ ├── loading.png │ │ ├── loading2.gif │ │ ├── PackageIcon.png │ │ ├── appleupdate.png │ │ ├── arrow-down.gif │ │ └── screensharing.png │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.ttf │ │ └── glyphicons-halflings-regular.woff │ ├── font-awesome-4.3.0 │ │ ├── fonts │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ └── fontawesome-webfont.woff2 │ │ ├── less │ │ │ ├── fixed-width.less │ │ │ ├── bordered-pulled.less │ │ │ ├── larger.less │ │ │ ├── list.less │ │ │ ├── font-awesome.less │ │ │ ├── core.less │ │ │ ├── stacked.less │ │ │ ├── rotated-flipped.less │ │ │ ├── path.less │ │ │ ├── animated.less │ │ │ └── mixins.less │ │ └── scss │ │ │ ├── _fixed-width.scss │ │ │ ├── _bordered-pulled.scss │ │ │ ├── _larger.scss │ │ │ ├── _list.scss │ │ │ ├── font-awesome.scss │ │ │ ├── _core.scss │ │ │ ├── _stacked.scss │ │ │ ├── _rotated-flipped.scss │ │ │ ├── _path.scss │ │ │ ├── _animated.scss │ │ │ └── _mixins.scss │ ├── css │ │ ├── smoothness │ │ │ └── images │ │ │ │ ├── ui-icons_222222_256x240.png │ │ │ │ ├── ui-icons_228ef1_256x240.png │ │ │ │ ├── ui-icons_ef8c08_256x240.png │ │ │ │ ├── ui-icons_ffd27a_256x240.png │ │ │ │ ├── ui-icons_ffffff_256x240.png │ │ │ │ ├── ui-bg_flat_10_000000_40x100.png │ │ │ │ ├── ui-bg_glass_100_f6f6f6_1x400.png │ │ │ │ ├── ui-bg_glass_100_fdf5ce_1x400.png │ │ │ │ ├── ui-bg_glass_65_ffffff_1x400.png │ │ │ │ ├── ui-bg_gloss-wave_35_f6a828_500x100.png │ │ │ │ ├── ui-bg_diagonals-thick_18_b81900_40x40.png │ │ │ │ ├── ui-bg_diagonals-thick_20_666666_40x40.png │ │ │ │ ├── ui-bg_highlight-soft_100_eeeeee_1x100.png │ │ │ │ └── ui-bg_highlight-soft_75_ffe45c_1x100.png │ │ ├── plugins │ │ │ ├── morris.css │ │ │ ├── metisMenu │ │ │ │ ├── metisMenu.min.css │ │ │ │ └── metisMenu.css │ │ │ ├── timeline.css │ │ │ └── dataTables.bootstrap.css │ │ ├── bootstrapxl.css │ │ └── sb-admin-2.css │ └── js │ │ ├── sb-admin-2.js │ │ ├── plugins │ │ ├── metisMenu │ │ │ ├── metisMenu.min.js │ │ │ └── metisMenu.js │ │ ├── flot │ │ │ ├── jquery.flot.resize.js │ │ │ └── jquery.flot.tooltip.min.js │ │ ├── morris │ │ │ └── morris-data.js │ │ └── dataTables │ │ │ └── dataTables.bootstrap.js │ │ ├── webadmin.js │ │ └── bootbox.min.js ├── templates │ ├── 404.html │ ├── 500.html │ ├── registration │ │ └── login.html │ └── base.html ├── processor.py ├── wsgi.py ├── urls.py ├── system_settings.py └── settings_template.py ├── docker ├── django │ ├── admin_tools │ │ ├── __init__.py │ │ └── management │ │ │ ├── __init__.py │ │ │ └── commands │ │ │ ├── __init__.py │ │ │ └── update_admin_user.py │ ├── requirements.txt │ └── passenger_wsgi.py ├── known_hosts ├── nginx │ ├── nginx-env.conf │ └── munkido.conf ├── run.sh ├── Makefile ├── id_rsa ├── Dockerfile ├── settings.py ├── README.md └── settings_import.py ├── .gitignore ├── manage.py ├── sal-client-setup.sh ├── munkido.wsgi ├── com.docker.machine.munkido.plist ├── Dockerfile └── docker-machine-munki-do-start.sh /pkgs/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /version: -------------------------------------------------------------------------------- 1 | v0.4.0 2 | -------------------------------------------------------------------------------- /catalogs/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /manifests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /munkido/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /catalogs/templatetags/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /munkido/templatetags/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docker/django/admin_tools/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docker/django/admin_tools/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /munkido/site_static/less/mixins.less: -------------------------------------------------------------------------------- 1 | // Mixins 2 | -------------------------------------------------------------------------------- /docker/django/admin_tools/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docker/django/requirements.txt: -------------------------------------------------------------------------------- 1 | django==1.7.2 2 | django-tokenapi==0.2.2 3 | psycopg2==2.5.5 4 | -------------------------------------------------------------------------------- /munkido/site_static/img/ssh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/img/ssh.png -------------------------------------------------------------------------------- /munkido/site_static/img/Munki.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/img/Munki.png -------------------------------------------------------------------------------- /munkido/site_static/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/img/logo.png -------------------------------------------------------------------------------- /munkido/site_static/img/arrow-up.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/img/arrow-up.gif -------------------------------------------------------------------------------- /munkido/site_static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/img/favicon.ico -------------------------------------------------------------------------------- /munkido/site_static/img/loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/img/loading.png -------------------------------------------------------------------------------- /munkido/site_static/img/loading2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/img/loading2.gif -------------------------------------------------------------------------------- /munkido/site_static/img/PackageIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/img/PackageIcon.png -------------------------------------------------------------------------------- /munkido/site_static/img/appleupdate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/img/appleupdate.png -------------------------------------------------------------------------------- /munkido/site_static/img/arrow-down.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/img/arrow-down.gif -------------------------------------------------------------------------------- /munkido/site_static/img/screensharing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/img/screensharing.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.pyo 3 | .DS_Store 4 | unused_* 5 | *.db 6 | *.pkg 7 | site_static/downloads/MunkiEnroll.pkg 8 | *.bak 9 | docker/known_hosts 10 | -------------------------------------------------------------------------------- /catalogs/templates/catalogs/dict_list.html: -------------------------------------------------------------------------------- 1 | {% for item in dict_list %} 2 | {% include "catalogs/generic_dict.html" with generic_dict=item only %} 3 | {% endfor %} -------------------------------------------------------------------------------- /catalogs/static/css/catalogs.css: -------------------------------------------------------------------------------- 1 | td.prewrap, td.code { 2 | white-space: pre-wrap; 3 | } 4 | td.code { 5 | font-family: Andale Mono, monospace; 6 | font-size: 9pt; 7 | } -------------------------------------------------------------------------------- /munkido/site_static/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /munkido/site_static/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /munkido/site_static/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/font-awesome-4.3.0/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /munkido/site_static/css/smoothness/images/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/css/smoothness/images/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /munkido/site_static/css/smoothness/images/ui-icons_228ef1_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/css/smoothness/images/ui-icons_228ef1_256x240.png -------------------------------------------------------------------------------- /munkido/site_static/css/smoothness/images/ui-icons_ef8c08_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/css/smoothness/images/ui-icons_ef8c08_256x240.png -------------------------------------------------------------------------------- /munkido/site_static/css/smoothness/images/ui-icons_ffd27a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/css/smoothness/images/ui-icons_ffd27a_256x240.png -------------------------------------------------------------------------------- /munkido/site_static/css/smoothness/images/ui-icons_ffffff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/css/smoothness/images/ui-icons_ffffff_256x240.png -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/font-awesome-4.3.0/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/font-awesome-4.3.0/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/font-awesome-4.3.0/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/font-awesome-4.3.0/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /munkido/site_static/css/smoothness/images/ui-bg_flat_10_000000_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/css/smoothness/images/ui-bg_flat_10_000000_40x100.png -------------------------------------------------------------------------------- /munkido/site_static/css/smoothness/images/ui-bg_glass_100_f6f6f6_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/css/smoothness/images/ui-bg_glass_100_f6f6f6_1x400.png -------------------------------------------------------------------------------- /munkido/site_static/css/smoothness/images/ui-bg_glass_100_fdf5ce_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/css/smoothness/images/ui-bg_glass_100_fdf5ce_1x400.png -------------------------------------------------------------------------------- /munkido/site_static/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/less/fixed-width.less: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .@{fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /docker/known_hosts: -------------------------------------------------------------------------------- 1 | [192.168.168.134]:10022 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGwV+xQ/+6uhbv4FpQ8WP3zvsbEwfwg/v6iOdqEig3KVZW+UrLrupnjvud5QvNXs8/2XVHLbJYF9WMfL2aibMhs= 2 | -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/scss/_fixed-width.scss: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .#{$fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /munkido/site_static/css/smoothness/images/ui-bg_gloss-wave_35_f6a828_500x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/css/smoothness/images/ui-bg_gloss-wave_35_f6a828_500x100.png -------------------------------------------------------------------------------- /munkido/site_static/css/smoothness/images/ui-bg_diagonals-thick_18_b81900_40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/css/smoothness/images/ui-bg_diagonals-thick_18_b81900_40x40.png -------------------------------------------------------------------------------- /munkido/site_static/css/smoothness/images/ui-bg_diagonals-thick_20_666666_40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/css/smoothness/images/ui-bg_diagonals-thick_20_666666_40x40.png -------------------------------------------------------------------------------- /munkido/site_static/css/smoothness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/css/smoothness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png -------------------------------------------------------------------------------- /munkido/site_static/css/smoothness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahampugh/munki-do/HEAD/munkido/site_static/css/smoothness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png -------------------------------------------------------------------------------- /catalogs/templates/catalogs/generic_dict.html: -------------------------------------------------------------------------------- 1 | 2 | {% for key, value in generic_dict.items %} 3 | 4 | {% endfor %} 5 |
{{ key }}{{ value }}
6 | -------------------------------------------------------------------------------- /munkido/templates/404.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Page not found{% endblock %} 4 | 5 | {% block content %} 6 |

Page not found

7 | 8 |

Sorry, but the requested page could not be found.

9 | {% endblock %} -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os, sys 3 | 4 | if __name__ == "__main__": 5 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "munkido.settings") 6 | 7 | from django.core.management import execute_from_command_line 8 | 9 | execute_from_command_line(sys.argv) -------------------------------------------------------------------------------- /catalogs/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import patterns, include, url 2 | 3 | urlpatterns = patterns('catalogs.views', 4 | url(r'^$', 'catalog_view'), 5 | url(r'^(?P[^/]+)/$', 'catalog_view'), 6 | url(r'^(?P[^/]+)/(?P\d+)/$', 'item_detail'), 7 | ) -------------------------------------------------------------------------------- /docker/django/passenger_wsgi.py: -------------------------------------------------------------------------------- 1 | import sys, os 2 | current_dir = os.path.dirname( os.path.abspath( __file__ ) ) 3 | sys.path.append( current_dir ) 4 | os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' 5 | import django.core.handlers.wsgi 6 | application = django.core.handlers.wsgi.WSGIHandler() 7 | -------------------------------------------------------------------------------- /munkido/templatetags/base_extras.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | from django.core.urlresolvers import reverse 3 | 4 | register = template.Library() 5 | 6 | @register.simple_tag 7 | def navactive(request, urls): 8 | if request.path in ( reverse(url) for url in urls.split() ): 9 | return "active" 10 | return "" -------------------------------------------------------------------------------- /munkido/templates/500.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Page not found{% endblock %} 4 | 5 | {% block content %} 6 |

Page unavailable

7 | 8 |

Sorry, but the requested page is unavailable due to a 9 | server hiccup.

10 | 11 |

Our engineers have been notified, so check back later.

12 | {% endblock %} -------------------------------------------------------------------------------- /docker/nginx/nginx-env.conf: -------------------------------------------------------------------------------- 1 | # Environment Variables for settings.py 2 | env DB_NAME; 3 | env DB_USER; 4 | env DB_PASS; 5 | env DB_PORT_5432_TCP_ADDR; 6 | env DB_PORT_5432_TCP_PORT; 7 | env TIME_ZONE; 8 | env APPNAME; 9 | env MUNKI_REPO_DIR; 10 | env MANIFEST_USERNAME_KEY; 11 | env MANIFEST_USERNAME_IS_EDITABLE; 12 | env WARRANTY_LOOKUP_ENABLED; 13 | env MODEL_LOOKUP_ENABLED; 14 | 15 | -------------------------------------------------------------------------------- /sal-client-setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # set the URL of the Sal server 4 | defaults write /Library/Preferences/com.github.salopensource.sal ServerURL http://sal.somewhere.com 5 | 6 | # set the Sal Machine Group key 7 | defaults write /Library/Preferences/com.github.salopensource.sal key q8bsrkcnpogpodhjbnfhhdi0l5324keypmh31rxvkffgixr41oohyfji106wvumjazn0bssbjmju9vsfxwtw4s5zxfoez53ytmhzagp0aqiprxjbu2rbovpvzs4t0elu 8 | 9 | -------------------------------------------------------------------------------- /pkgs/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import patterns, include, url 2 | 3 | urlpatterns = patterns('pkgs.views', 4 | url(r'^index/*$', 'index'), 5 | url(r'^orphaned/*$', 'orphaned'), 6 | url(r'^confirm/*$', 'confirm'), 7 | url(r'^done/*$', 'done'), 8 | url(r'^deleted/*$', 'deleted'), 9 | url(r'^gitpull$', 'gitpull'), 10 | url(r'^(?P[^/]+)/$', 'index'), 11 | url(r'^$', 'index'), 12 | ) -------------------------------------------------------------------------------- /munkido/site_static/less/variables.less: -------------------------------------------------------------------------------- 1 | // Variables 2 | 3 | @gray-darker: lighten(#000, 13.5%); 4 | @gray-dark: lighten(#000, 20%); 5 | @gray: lighten(#000, 33.5%); 6 | @gray-light: lighten(#000, 60%); 7 | @gray-lighter: lighten(#000, 93.5%); 8 | @gray-lightest: lighten(#000, 97.25%); 9 | @brand-primary: #428bca; 10 | @brand-success: #5cb85c; 11 | @brand-info: #5bc0de; 12 | @brand-warning: #f0ad4e; 13 | @brand-danger: #d9534f; 14 | 15 | -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/less/bordered-pulled.less: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em @fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .pull-right { float: right; } 11 | .pull-left { float: left; } 12 | 13 | .@{fa-css-prefix} { 14 | &.pull-left { margin-right: .3em; } 15 | &.pull-right { margin-left: .3em; } 16 | } 17 | -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/scss/_bordered-pulled.scss: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em $fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .pull-right { float: right; } 11 | .pull-left { float: left; } 12 | 13 | .#{$fa-css-prefix} { 14 | &.pull-left { margin-right: .3em; } 15 | &.pull-right { margin-left: .3em; } 16 | } 17 | -------------------------------------------------------------------------------- /catalogs/tests.py: -------------------------------------------------------------------------------- 1 | """ 2 | This file demonstrates writing tests using the unittest module. These will pass 3 | when you run "manage.py test". 4 | 5 | Replace this with more appropriate tests for your application. 6 | """ 7 | 8 | from django.test import TestCase 9 | 10 | 11 | class SimpleTest(TestCase): 12 | def test_basic_addition(self): 13 | """ 14 | Tests that 1 + 1 always equals 2. 15 | """ 16 | self.assertEqual(1 + 1, 2) 17 | -------------------------------------------------------------------------------- /manifests/tests.py: -------------------------------------------------------------------------------- 1 | """ 2 | This file demonstrates writing tests using the unittest module. These will pass 3 | when you run "manage.py test". 4 | 5 | Replace this with more appropriate tests for your application. 6 | """ 7 | 8 | from django.test import TestCase 9 | 10 | 11 | class SimpleTest(TestCase): 12 | def test_basic_addition(self): 13 | """ 14 | Tests that 1 + 1 always equals 2. 15 | """ 16 | self.assertEqual(1 + 1, 2) 17 | -------------------------------------------------------------------------------- /munkido/site_static/css/plugins/morris.css: -------------------------------------------------------------------------------- 1 | .morris-hover{position:absolute;z-index:1000}.morris-hover.morris-default-style{border-radius:10px;padding:6px;color:#666;background:rgba(255,255,255,0.8);border:solid 2px rgba(230,230,230,0.8);font-family:sans-serif;font-size:12px;text-align:center}.morris-hover.morris-default-style .morris-hover-row-label{font-weight:bold;margin:0.25em 0} 2 | .morris-hover.morris-default-style .morris-hover-point{white-space:nowrap;margin:0.1em 0} 3 | -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/less/larger.less: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .@{fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .@{fa-css-prefix}-2x { font-size: 2em; } 11 | .@{fa-css-prefix}-3x { font-size: 3em; } 12 | .@{fa-css-prefix}-4x { font-size: 4em; } 13 | .@{fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/scss/_larger.scss: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .#{$fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .#{$fa-css-prefix}-2x { font-size: 2em; } 11 | .#{$fa-css-prefix}-3x { font-size: 3em; } 12 | .#{$fa-css-prefix}-4x { font-size: 4em; } 13 | .#{$fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /docker/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd $APP_DIR 4 | ADMIN_PASS=${ADMIN_PASS:-} 5 | python manage.py syncdb 6 | python manage.py makemigrations 7 | python manage.py migrate 8 | 9 | echo "from django.contrib.auth.models import User; User.objects.create_superuser('admin', 'docker@localhost', 'password')" | python manage.py shell 10 | 11 | export DJANGO_SETTINGS_MODULE='munkido.settings' 12 | 13 | python manage.py collectstatic --noinput 14 | 15 | python manage.py runserver 0.0.0.0:8000 16 | 17 | -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/less/list.less: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: @fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .@{fa-css-prefix}-li { 11 | position: absolute; 12 | left: -@fa-li-width; 13 | width: @fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.@{fa-css-prefix}-lg { 17 | left: (-@fa-li-width + (4em / 14)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/scss/_list.scss: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: $fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .#{$fa-css-prefix}-li { 11 | position: absolute; 12 | left: -$fa-li-width; 13 | width: $fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.#{$fa-css-prefix}-lg { 17 | left: -$fa-li-width + (4em / 14); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /manifests/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import patterns, include, url 2 | 3 | urlpatterns = patterns('manifests.views', 4 | url(r'^$', 'index', name="mdo-catalogs"), 5 | url(r'^new$', 'new'), 6 | url(r'^copymanifest$', 'copymanifest'), 7 | url(r'^delete/(?P[^/]+)/$', 'delete'), 8 | url(r'^#(?P.+)/$', 'index'), 9 | url(r'^gitpull$', 'gitpull'), 10 | url(r'^view/(?P[^/]+)/$', 'view'), 11 | url(r'^detail/(?P[^/]+)$', 'detail'), 12 | ) -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/scss/font-awesome.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.3.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables"; 7 | @import "mixins"; 8 | @import "path"; 9 | @import "core"; 10 | @import "larger"; 11 | @import "fixed-width"; 12 | @import "list"; 13 | @import "bordered-pulled"; 14 | @import "animated"; 15 | @import "rotated-flipped"; 16 | @import "stacked"; 17 | @import "icons"; 18 | -------------------------------------------------------------------------------- /catalogs/static/css/tapdrop.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Tab drop for Bootstrap 3 | * 4 | * Copyright 2012 Stefan Petre 5 | * Improvements by Jenna Schabdach 6 | * Licensed under the Apache License v2.0 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | */ 10 | .nav-tabs, 11 | .nav-pills { 12 | position: relative; 13 | } 14 | 15 | /* adjust as needed so the tab text displays */ 16 | .tabdrop{ 17 | width: 50px; 18 | } 19 | 20 | /* hide any icons found in tabs not on first line */ 21 | .nav-tabs li li i{ 22 | visibility: hidden; 23 | } -------------------------------------------------------------------------------- /munkido/processor.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse, HttpRequest, HttpResponseRedirect 2 | from django.template import RequestContext 3 | from django.shortcuts import render_to_response 4 | from django.core.context_processors import csrf 5 | from django.conf import settings 6 | 7 | from django.contrib.auth.models import User, Group 8 | PROJECT_DIR = settings.PROJECT_DIR 9 | APPNAME = settings.APPNAME 10 | 11 | def index(request): 12 | handle=open(PROJECT_DIR+"/../version", 'r+') 13 | version=handle.read() 14 | return { 15 | 'webadmin_version': version} 16 | 17 | -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/less/font-awesome.less: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.3.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables.less"; 7 | @import "mixins.less"; 8 | @import "path.less"; 9 | @import "core.less"; 10 | @import "larger.less"; 11 | @import "fixed-width.less"; 12 | @import "list.less"; 13 | @import "bordered-pulled.less"; 14 | @import "animated.less"; 15 | @import "rotated-flipped.less"; 16 | @import "stacked.less"; 17 | @import "icons.less"; 18 | -------------------------------------------------------------------------------- /munkido.wsgi: -------------------------------------------------------------------------------- 1 | import os, sys 2 | import site 3 | 4 | MUNKIDO_ENV_DIR = '/var/www/html/munkido' 5 | 6 | # Use site to load the site-packages directory of our virtualenv 7 | site.addsitedir(os.path.join(MUNKIDO_ENV_DIR, 'lib/python2.7/site-packages')) 8 | 9 | # Make sure we have the virtualenv and the Django app itself added to our path 10 | sys.path.append(MUNKIDO_ENV_DIR) 11 | sys.path.append(os.path.join(MUNKIDO_ENV_DIR, 'munkido')) 12 | 13 | os.environ['DJANGO_SETTINGS_MODULE'] = 'munkido.settings' 14 | 15 | import django.core.handlers.wsgi 16 | application = django.core.handlers.wsgi.WSGIHandler() -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/less/core.less: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal @fa-font-size-base/1 FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | transform: translate(0, 0); // ensures no half-pixel rendering in firefox 12 | 13 | } 14 | -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/less/stacked.less: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .@{fa-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .@{fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .@{fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .@{fa-css-prefix}-inverse { color: @fa-inverse; } 21 | -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/scss/_core.scss: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal #{$fa-font-size-base}/1 FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | transform: translate(0, 0); // ensures no half-pixel rendering in firefox 12 | 13 | } 14 | -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/scss/_stacked.scss: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .#{$fa-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .#{$fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .#{$fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .#{$fa-css-prefix}-inverse { color: $fa-inverse; } 21 | -------------------------------------------------------------------------------- /munkido/site_static/css/plugins/metisMenu/metisMenu.min.css: -------------------------------------------------------------------------------- 1 | .arrow{float:right}.glyphicon.arrow:before{content:"\e079"}.active>a>.glyphicon.arrow:before{content:"\e114"}.fa.arrow:before{content:"\f104"}.active>a>.fa.arrow:before{content:"\f107"}.plus-times{float:right}.fa.plus-times:before{content:"\f067"}.active>a>.fa.plus-times{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.plus-minus{float:right}.fa.plus-minus:before{content:"\f067"}.active>a>.fa.plus-minus:before{content:"\f068"} -------------------------------------------------------------------------------- /docker/nginx/munkido.conf: -------------------------------------------------------------------------------- 1 | # webapp.conf: 2 | server { 3 | listen 8000; 4 | server_name docker.whitbylab.org; 5 | root /home/app/munkido/static; 6 | 7 | # The following deploys your Ruby/Python/Node.js/Meteor app on Passenger. 8 | 9 | # Not familiar with Passenger, and used (G)Unicorn/Thin/Puma/pure Node before? 10 | # Yes, this is all you need to deploy on Passenger! All the reverse proxying, 11 | # socket setup, process management, etc are all taken care automatically for 12 | # you! Learn more at https://www.phusionpassenger.com/. 13 | passenger_enabled on; 14 | passenger_user app; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /manifests/templates/manifests/delete.html: -------------------------------------------------------------------------------- 1 | {% block content %} 2 | 3 | 7 | 16 | 17 | {% endblock content %} -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/less/rotated-flipped.less: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); } 5 | .@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); } 6 | .@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); } 7 | 8 | .@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); } 9 | .@{fa-css-prefix}-flip-vertical { .fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .@{fa-css-prefix}-rotate-90, 15 | :root .@{fa-css-prefix}-rotate-180, 16 | :root .@{fa-css-prefix}-rotate-270, 17 | :root .@{fa-css-prefix}-flip-horizontal, 18 | :root .@{fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /com.docker.machine.munkido.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | EnvironmentVariables 6 | 7 | PATH 8 | /usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin 9 | 10 | Label 11 | com.docker.machine.munkido 12 | ProgramArguments 13 | 14 | /usr/local/bin/docker-machine 15 | start 16 | munkido 17 | 18 | RunAtLoad 19 | 20 | 21 | -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/scss/_rotated-flipped.scss: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); } 5 | .#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); } 6 | .#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); } 7 | 8 | .#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); } 9 | .#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .#{$fa-css-prefix}-rotate-90, 15 | :root .#{$fa-css-prefix}-rotate-180, 16 | :root .#{$fa-css-prefix}-rotate-270, 17 | :root .#{$fa-css-prefix}-flip-horizontal, 18 | :root .#{$fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /pkgs/templates/pkgs/done.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | 4 | {% block page_title %}Packages{% endblock %} 5 | 6 | {% block navbar-default_extensions %} 7 |
8 | {% if confirm_move %} 9 |

Packages have been moved to a new catalog

10 | {% elif confirm_add %} 11 |

Packages have been added to a new catalog

12 | {% else %} 13 |

Packages have been removed from a catalog

14 | {% endif %} 15 |
16 | {% endblock %} 17 | 18 | {% block content %} 19 | 20 | {% if done %} 21 |

Back to the Packages page

22 | {% else %} 23 |

Error: No Packages were selected.

24 | {% endif %} 25 | {% endblock content %} -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/less/path.less: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}'); 7 | src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'), 8 | url('@{fa-font-path}/fontawesome-webfont.woff2?v=@{fa-version}') format('woff2'), 9 | url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'), 10 | url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'), 11 | url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/scss/_path.scss: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}'); 7 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'), 8 | url('#{$fa-font-path}/fontawesome-webfont.woff2?v=#{$fa-version}') format('woff2'), 9 | url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'), 10 | url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'), 11 | url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/less/animated.less: -------------------------------------------------------------------------------- 1 | // Animated Icons 2 | // -------------------------- 3 | 4 | .@{fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .@{fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/scss/_animated.scss: -------------------------------------------------------------------------------- 1 | // Spinning Icons 2 | // -------------------------- 3 | 4 | .#{$fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .#{$fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /pkgs/templates/pkgs/deleted.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | 4 | {% block page_title %}Packages{% endblock %} 5 | 6 | {% block navbar-default_extensions %} 7 |
8 |

Packages Deleted

9 |
10 | {% endblock %} 11 | 12 | {% block content %} 13 | 14 | {% if deleted %} 15 |

Makecatalogs has updated the catalogs. The following packages were deleted:

16 | 17 | 18 | {% for package in deleted_packages %} 19 | 20 | 21 | 22 | {% endfor %} 23 | 24 |
{{ package }}
25 | 26 |

Back to the Packages page

27 | {% else %} 28 |

No Packages were selected.

29 | {% endif %} 30 | {% endblock content %} -------------------------------------------------------------------------------- /docker/Makefile: -------------------------------------------------------------------------------- 1 | DOCKER_USER=grahamrpugh 2 | NAME=munki-do 3 | MUNKI_REPO="/Users/Shared/munki_repo" 4 | MWA_PORT=8000 5 | DB_CONTAINER_NAME="/Users/Shared/munki-do-db" 6 | GIT_PATH='' 7 | GIT_IGNORE_PKGS='' 8 | GIT_BRANCHING='' 9 | MANIFEST_RESTRICTION_KEY='' 10 | DOCKER_RUN_COMMON=--name munki-do -p ${MWA_PORT}:8000 -v ${MUNKI_REPO{:/munki_repo -v ${DB_CONTAINER_NAME}:/munki-do-db -e DOCKER_MUNKIDO_GIT_PATH="${GIT_PATH}" -e DOCKER_MUNKIDO_GIT_BRANCHING="${GIT_BRANCHING}" -e DOCKER_MUNKIDO_GIT_IGNORE_PKGS="${GIT_IGNORE_PKGS}" -e DOCKER_MUNKIDO_MANIFEST_RESTRICTION_KEY="{$MANIFEST_RESTRICTION_KEY}" ${DOCKER_USER}/${NAME} 11 | 12 | all: build 13 | 14 | build: 15 | docker build -t="${DOCKER_USER}/${NAME}" . 16 | 17 | run: 18 | # mkdir -p ${MUNKI_REPO_DIR} 19 | docker run -d --restart=always ${DOCKER_RUN_COMMON} 20 | 21 | clean: 22 | docker stop $(NAME) 23 | docker rm $(NAME) 24 | 25 | bash: 26 | docker exec -t -i $(NAME) /bin/bash 27 | 28 | -------------------------------------------------------------------------------- /munkido/site_static/js/sb-admin-2.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | $('#side-menu').metisMenu(); 3 | }); 4 | 5 | //Loads the correct sidebar on window load, 6 | //collapses the sidebar on window resize. 7 | // Sets the min-height of #page-wrapper to window size 8 | $(function() { 9 | $(window).bind("load resize", function() { 10 | topOffset = 50; 11 | width = (this.window.innerWidth > 0) ? this.window.innerWidth : this.screen.width; 12 | if (width < 768) { 13 | $('div.navbar-collapse').addClass('collapse') 14 | topOffset = 100; // 2-row-menu 15 | } else { 16 | $('div.navbar-collapse').removeClass('collapse') 17 | } 18 | 19 | height = (this.window.innerHeight > 0) ? this.window.innerHeight : this.screen.height; 20 | height = height - topOffset; 21 | if (height < 1) height = 1; 22 | if (height > topOffset) { 23 | $("#page-wrapper").css("min-height", (height) + "px"); 24 | } 25 | }) 26 | }) 27 | -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/less/mixins.less: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | .fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal @fa-font-size-base/1 FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | transform: translate(0, 0); // ensures no half-pixel rendering in firefox 12 | 13 | } 14 | 15 | .fa-icon-rotate(@degrees, @rotation) { 16 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation); 17 | -webkit-transform: rotate(@degrees); 18 | -ms-transform: rotate(@degrees); 19 | transform: rotate(@degrees); 20 | } 21 | 22 | .fa-icon-flip(@horiz, @vert, @rotation) { 23 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation, mirror=1); 24 | -webkit-transform: scale(@horiz, @vert); 25 | -ms-transform: scale(@horiz, @vert); 26 | transform: scale(@horiz, @vert); 27 | } 28 | -------------------------------------------------------------------------------- /munkido/site_static/font-awesome-4.3.0/scss/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | @mixin fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal #{$fa-font-size-base}/1 FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | transform: translate(0, 0); // ensures no half-pixel rendering in firefox 12 | 13 | } 14 | 15 | @mixin fa-icon-rotate($degrees, $rotation) { 16 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}); 17 | -webkit-transform: rotate($degrees); 18 | -ms-transform: rotate($degrees); 19 | transform: rotate($degrees); 20 | } 21 | 22 | @mixin fa-icon-flip($horiz, $vert, $rotation) { 23 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}); 24 | -webkit-transform: scale($horiz, $vert); 25 | -ms-transform: scale($horiz, $vert); 26 | transform: scale($horiz, $vert); 27 | } 28 | -------------------------------------------------------------------------------- /munkido/site_static/js/plugins/metisMenu/metisMenu.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * metismenu - v1.0.3 3 | * Easy menu jQuery plugin for Twitter Bootstrap 3 4 | * https://github.com/onokumus/metisMenu 5 | * 6 | * Made by Osman Nuri Okumuş 7 | * Under MIT License 8 | */ 9 | !function(a,b,c){function d(b,c){this.element=b,this.settings=a.extend({},f,c),this._defaults=f,this._name=e,this.init()}var e="metisMenu",f={toggle:!0};d.prototype={init:function(){var b=a(this.element),c=this.settings.toggle;this.isIE()<=9?(b.find("li.active").has("ul").children("ul").collapse("show"),b.find("li").not(".active").has("ul").children("ul").collapse("hide")):(b.find("li.active").has("ul").children("ul").addClass("collapse in"),b.find("li").not(".active").has("ul").children("ul").addClass("collapse")),b.find("li").has("ul").children("a").on("click",function(b){b.preventDefault(),a(this).parent("li").toggleClass("active").children("ul").collapse("toggle"),c&&a(this).parent("li").siblings().removeClass("active").children("ul.in").collapse("hide")})},isIE:function(){for(var a,b=3,d=c.createElement("div"),e=d.getElementsByTagName("i");d.innerHTML="",e[0];)return b>4?b:a}},a.fn[e]=function(b){return this.each(function(){a.data(this,"plugin_"+e)||a.data(this,"plugin_"+e,new d(this,b))})}}(jQuery,window,document); -------------------------------------------------------------------------------- /manifests/templates/manifests/new.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load url from future %} 3 | 4 | {% block extra_style %} 5 | 10 | {% endblock %} 11 | {% block java_script %} 12 | {% load static %} 13 | 18 | {% endblock %} 19 | 20 | 21 | {% block page_title %}Manifests{% endblock %} 22 | 23 | {% block content %} 24 |
25 | {% csrf_token %} 26 |
27 |

Create new manifest

28 |
29 | 30 | {{ form.manifest_name }} 31 |
32 | 33 | 34 |
35 |
36 |
37 | {% endblock content %} -------------------------------------------------------------------------------- /munkido/site_static/css/plugins/metisMenu/metisMenu.css: -------------------------------------------------------------------------------- 1 | /* 2 | * metismenu - v1.0.3 3 | * Easy menu jQuery plugin for Twitter Bootstrap 3 4 | * https://github.com/onokumus/metisMenu 5 | * 6 | * Made by Osman Nuri Okumuş 7 | * Under MIT License 8 | */ 9 | .arrow { 10 | float: right; 11 | } 12 | 13 | .glyphicon.arrow:before { 14 | content: "\e079"; 15 | } 16 | 17 | .active > a > .glyphicon.arrow:before { 18 | content: "\e114"; 19 | } 20 | 21 | 22 | /* 23 | * Require Font-Awesome 24 | * http://fortawesome.github.io/Font-Awesome/ 25 | */ 26 | 27 | 28 | .fa.arrow:before { 29 | content: "\f104"; 30 | } 31 | 32 | .active > a > .fa.arrow:before { 33 | content: "\f107"; 34 | } 35 | 36 | .plus-times { 37 | float: right; 38 | } 39 | 40 | .fa.plus-times:before { 41 | content: "\f067"; 42 | } 43 | 44 | .active > a > .fa.plus-times { 45 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); 46 | -webkit-transform: rotate(45deg); 47 | -moz-transform: rotate(45deg); 48 | -ms-transform: rotate(45deg); 49 | -o-transform: rotate(45deg); 50 | transform: rotate(45deg); 51 | } 52 | 53 | .plus-minus { 54 | float: right; 55 | } 56 | 57 | .fa.plus-minus:before { 58 | content: "\f067"; 59 | } 60 | 61 | .active > a > .fa.plus-minus:before { 62 | content: "\f068"; 63 | } -------------------------------------------------------------------------------- /pkgs/static/js/pkgs.js: -------------------------------------------------------------------------------- 1 | // Search fields 2 | // Main Search 3 | $(document).ready(function() { 4 | $('#SearchField').keyup(function(){ 5 | var filter = $(this).val(); 6 | var regExPattern = "gi"; 7 | var regEx = new RegExp(filter, regExPattern); 8 | $('#listbig a').each(function(){ 9 | if ( 10 | $(this).text().search(new RegExp(filter, "i")) < 0 && 11 | $(this).data('state').search(regEx) < 0 12 | ){ 13 | $(this).hide(); 14 | } else { 15 | $(this).show(); 16 | } 17 | }); 18 | }); 19 | $('#SearchFieldMobile').keyup(function(){ 20 | var filter = $(this).val(); 21 | var regExPattern = "gi"; 22 | var regEx = new RegExp(filter, regExPattern); 23 | $('#listbig a').each(function(){ 24 | if ( 25 | $(this).text().search(new RegExp(filter, "i")) < 0 && 26 | $(this).data('state').search(regEx) < 0 27 | ){ 28 | $(this).hide(); 29 | } else { 30 | $(this).show(); 31 | } 32 | }); 33 | }); 34 | 35 | $('#SearchField').change(function(){ 36 | $('#SearchField').keyup(); 37 | }); 38 | 39 | $('#SearchFieldMobile').change(function(){ 40 | $('#SearchFieldMobile').keyup(); 41 | }); 42 | }); 43 | 44 | function toggle(source) { 45 | checkboxes = document.getElementsByName('items_to_move[]'); 46 | for(var i=0, n=checkboxes.length;i 4 | {% block page_title %}Packages{% endblock %} 5 | 6 | {% block navbar-default_extensions %} 7 |
8 | Orphaned packages 9 |
10 | {% endblock %} 11 | 12 | {% block content %} 13 | {% if orphaned_pkgs %} 14 |
15 | {% csrf_token %} 16 | {% if delete_pkgs %} 17 |
18 | 19 | {% endif %} 20 |
21 | 22 |

23 | 24 | 25 | 26 | 27 | {% if delete_pkgs %} 28 | 29 | {% endif %} 30 | 31 | 32 | 33 | {% for pkg in orphaned_pkgs %} 34 | 35 | 36 | {% if change_pkgs or delete_pkgs %} 37 | 40 | {% endif %} 41 | 42 | {% endfor %} 43 | 44 |
Package locationCheck to select
{{ pkg }} 38 |
39 |
45 |

46 | {% else %} 47 |

There are no Orphaned Packages at this time.

48 |

Back to the Packages page

49 | {% endif %} 50 | {% endblock content %} -------------------------------------------------------------------------------- /munkido/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for munkiwebadmin project. 3 | 4 | This module contains the WSGI application used by Django's development server 5 | and any production WSGI deployments. It should expose a module-level variable 6 | named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover 7 | this application via the ``WSGI_APPLICATION`` setting. 8 | 9 | Usually you will have the standard Django WSGI application here, but it also 10 | might make sense to replace the whole Django WSGI application with a custom one 11 | that later delegates to the Django one. For example, you could introduce WSGI 12 | middleware here, or combine a Django application with an application of another 13 | framework. 14 | 15 | """ 16 | import os 17 | 18 | # We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks 19 | # if running multiple sites in the same mod_wsgi process. To fix this, use 20 | # mod_wsgi daemon mode with each site in its own daemon process, or use 21 | # os.environ["DJANGO_SETTINGS_MODULE"] = "munkiwebadmin.settings" 22 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "munkiwebadmin.settings") 23 | 24 | # This application object is used by any WSGI server configured to use this 25 | # file. This includes Django's development server, if the WSGI_APPLICATION 26 | # setting points here. 27 | from django.core.wsgi import get_wsgi_application 28 | application = get_wsgi_application() 29 | 30 | # Apply WSGI middleware here. 31 | # from helloworld.wsgi import HelloWorldApplication 32 | # application = HelloWorldApplication(application) 33 | -------------------------------------------------------------------------------- /munkido/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import patterns, include, url 2 | from django.conf import settings 3 | from django.contrib.staticfiles.urls import staticfiles_urlpatterns 4 | 5 | # Uncomment the next two lines to enable the admin: 6 | from django.contrib import admin 7 | admin.autodiscover() 8 | 9 | urlpatterns = patterns('', 10 | # Uncomment the admin/doc line below to enable admin documentation: 11 | # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), 12 | 13 | # Uncomment the next line to enable the admin: 14 | url(r'^admin/', include(admin.site.urls)), 15 | 16 | url(r'^login/$', 'django.contrib.auth.views.login', name='login'), 17 | url(r'^logout/$', 'django.contrib.auth.views.logout_then_login', name='logout'), 18 | url(r'^manifest/', include('manifests.urls')), 19 | url(r'^catalog/', include('catalogs.urls')), 20 | url(r'^pkgs/', include('pkgs.urls')), 21 | 22 | # for compatibility with MunkiReport scripts 23 | url(r'^$', include('catalogs.urls')), 24 | url(r'', include('tokenapi.urls')), 25 | 26 | # for access to the munki repo directly: 27 | url(r'^munki_repo/(?P.*)$', 28 | 'django.views.static.serve', 29 | {'document_root': settings.MUNKI_PKG_ROOT, }), 30 | ) 31 | # comment out the following if you are serving 32 | # static files a different way 33 | urlpatterns += staticfiles_urlpatterns() 34 | 35 | if settings.DEBUG: 36 | urlpatterns += patterns('', 37 | url(r'^media/(?P.*)$', 38 | 'django.views.static.serve', 39 | {'document_root': settings.MEDIA_ROOT, }), 40 | ) -------------------------------------------------------------------------------- /docker/id_rsa: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEA0IyH8syuSCm3CBFw4LbvuZAHUxI5qqKqvGyOenuB1kETwd9E 3 | MlCMG9qF0npRK6KTMGADMNmKSnPA2kRj1C5i8dulEzj6tq0BNtRO2qst7LEi+eKS 4 | NumuwfTIbGZdXz1uKoPbiv5ebwZ8/qnEpKWczBI9MlS6iEDcQGlIchWJtucLhfIP 5 | S0wC1WCRLZ6f3xBIA6riJ7hFxg8LUqemGPkykVT/dn6qR3qPmP8dMZqI/m7wfLJd 6 | I2TzBk/oTUuQckcTiB4nC0wApPGpqMBjRXeWMr/4JreExdPo01L2cttOFS6q2Bmu 7 | qGhfPfjsjsbDVozT2Yo19Spk/wfaXl0clJHygQIDAQABAoIBAHc6oM6zLkCbeMTo 8 | E7ylWdChA07+8HEZprsq5RopWkV/1yfT2U1at3+FI1T+EUH9JGFXwvs+o82E+BDR 9 | YLGCA5d6l5mxzcR6jGMoZhymGQ9lBjYOzsEOQJcqtxsiOuekW0N7Nxzz6FFZSETg 10 | Ekh/VnFlTA9mWW5khodcqcpvfdhOnkpIsgz0+nPKIA94DO1E4/sQCLE3tGiFvL4c 11 | 0P/9h/MKc1rmYTGuyMd9gvzn2ETy0o1r118LXd3hjTV6IlwdMpKM4LvJJzsjyePt 12 | 2NM/ep2911nwS3mXPqkISxGVVbwCSDI/hAwsl5OIH9fMHlpSEsjB2FbWgTXK5byT 13 | XVLnrUECgYEA+dF2bOJdA7LMTThps/d+wXgiw8f6AzqqFUYF2r2oTpJP5WBI3f0r 14 | rZECF/X9/MYQpuwSbXmljlw4G5/ptyWf9lj65CbaChqZ//6EN/E2RnWBtKPVOvzX 15 | 4HQ0OkFXQ8W4ljjI5m0fp9D79kqw1DV37wOxtg/lKXH+vEA2AZQvqM0CgYEA1bWj 16 | QrdglYbZVFFO2t50hRjM4fBX7OQJx5biPpoMX+8K9iN7DTLU8nDkfQ7vWX2E9nPp 17 | cszLFZAbKtXxxQhUshthxRaANWy5MkoeBOVLFTemryNlN28M3cMgrMQ4bEB7+4Cg 18 | PfimL9BAsKEy/56v9OnR0tZiLLxs0hbgHdQMQIUCgYBuBZkRZTQvz8v4alLrRqHV 19 | lRJChU0PpQOJMPidGJAKYpe7XodY9QoKe+WfJeCBNb3Ztfh7rGqEYwr255un5HMp 20 | rJB6cL3wWzzdqHsUpDASIehI5SqguwBcQvFJgsNq/qZHyqR4DzE02G5PTx/HpfC3 21 | HDplA2UatrDIucLPOTMwNQKBgArIpptYO4RwEIljrPH4ZbLNpJEGGrm2bBPpNjNo 22 | fJVer5PqCGyLExnEvpLc7RD793ikMrR7RwgohGZt80w49mUiYpWaZA/OE65I9SjU 23 | FSzV6RBPXe0lKmYKUZzGLf6wZlEzlWJrKJ+jB5CiIbuqW0Clh9P2w290dp1HUDnR 24 | GGktAoGBANCt4hZk/CTCJWn6zXsQe6GTKMpWhBUM7WgVHIHw2MDIKZpAIQWbpMmf 25 | 6ziTCVgMPwdVISrS36gew5yxgpUHJ6NhhpWWrdHrLERcRNmy+5T8Clmft3NlYsMx 26 | CiVj32E8zn0bkBOzZ4eOuGh/O+c0PgV2ZhNtoALECZJDHa2husJr 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /catalogs/templatetags/catalog_extras.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | from django.template.defaultfilters import stringfilter 3 | from django.utils.html import conditional_escape 4 | from django.utils.safestring import mark_safe 5 | 6 | 7 | # Reference for creating custom filters and tags:- 8 | # https://docs.djangoproject.com/en/dev/howto/custom-template-tags/ 9 | 10 | register = template.Library() 11 | 12 | @register.filter(name='wrappable', needs_autoescape=True) 13 | @stringfilter 14 | def wrappable_filter(value, autoescape=None): 15 | """ 16 | Places zero-width breaking spaces in text to allow it to wrap 17 | before a underscore (_) or fullstop (.). The browser will use this 18 | as a hint as to where to wrap the text if required. 19 | """ 20 | 21 | # Escape the input text so that it's safe to display 22 | if autoescape: 23 | esc = conditional_escape 24 | else: 25 | esc = lambda x: x 26 | escaped_wrapped_text = '%s' % (esc(value)) 27 | 28 | # Add hints to the browser that it can wrap before a _ of . 29 | escaped_wrapped_text = escaped_wrapped_text.replace('_', '​_') 30 | escaped_wrapped_text = escaped_wrapped_text.replace('.', '​.') 31 | 32 | # Return the text marked as safe so that the new ​'s aren't escaped 33 | return mark_safe(escaped_wrapped_text) 34 | 35 | 36 | @register.filter 37 | def type_is(item, kind): 38 | """Returns the data type of the item (plist-style)""" 39 | if kind == 'string': 40 | return isinstance(item, basestring) 41 | if kind == 'boolean': 42 | return isinstance(item, bool) 43 | if kind == 'integer': 44 | return isinstance(item, int) 45 | if kind == 'float': 46 | return isinstance(item, float) 47 | if kind == 'array': 48 | return isinstance(item, list) 49 | if kind == 'dictionary': 50 | return isinstance(item, dict) 51 | return False 52 | type_is.is_safe = True 53 | -------------------------------------------------------------------------------- /catalogs/static/js/catalogs.js: -------------------------------------------------------------------------------- 1 | // Search fields 2 | // Main Search 3 | $(document).ready(function() { 4 | $('#SearchField').keyup(function(){ 5 | var filter = $(this).val(); 6 | var regExPattern = "gi"; 7 | var regEx = new RegExp(filter, regExPattern); 8 | $('#listbig a').each(function(){ 9 | if ( 10 | $(this).text().search(new RegExp(filter, "i")) < 0 && 11 | $(this).data('state').search(regEx) < 0 12 | ){ 13 | $(this).hide(); 14 | } else { 15 | $(this).show(); 16 | } 17 | }); 18 | }); 19 | $('#SearchFieldMobile').keyup(function(){ 20 | var filter = $(this).val(); 21 | var regExPattern = "gi"; 22 | var regEx = new RegExp(filter, regExPattern); 23 | $('#listbig a').each(function(){ 24 | if ( 25 | $(this).text().search(new RegExp(filter, "i")) < 0 && 26 | $(this).data('state').search(regEx) < 0 27 | ){ 28 | $(this).hide(); 29 | } else { 30 | $(this).show(); 31 | } 32 | }); 33 | }); 34 | 35 | $('#SearchField').change(function(){ 36 | $('#SearchField').keyup(); 37 | }); 38 | 39 | $('#SearchFieldMobile').change(function(){ 40 | $('#SearchFieldMobile').keyup(); 41 | }); 42 | }); 43 | 44 | function getCatalogItem(catalog_name, catalog_index, item_name, item_version) { 45 | var catalogItemURL = '/catalog/' + catalog_name + '/' + catalog_index + '/'; 46 | $.get(catalogItemURL, function(data) { 47 | $('#item_detail').html(data); 48 | }); 49 | $('.list-group-item[id="' + item_name + '"]').addClass('active'); 50 | $('.list-group-item[id!="' + item_name + '"]').removeClass('active'); 51 | $('.softwareversion[id!="' + item_name + '"]').addClass('hidden'); 52 | $('.softwareversion[id="' + item_name + '"]').removeClass('hidden'); 53 | $('.activetabs[id="' + item_version + '"]').addClass('active'); 54 | $('.activetabs[id!="' + item_version + '"]').removeClass('active'); 55 | $('.nav-tabs').tabdrop('layout'); 56 | } 57 | 58 | function sideSecific() { 59 | } 60 | 61 | function setviews() { 62 | } -------------------------------------------------------------------------------- /catalogs/templates/catalogs/item_detail.html: -------------------------------------------------------------------------------- 1 | {% load catalog_extras %} 2 | 3 | 4 | 5 | {% for key, value in catalog_item.items %} 6 | {% if 'installer_item_location' in key %} 7 | {# provide download link for the package #} 8 | 9 | {% elif key == 'name' %} 10 | {# provide link to the packages page #} 11 | 12 | {% elif value|type_is:'array' %} 13 | {% if value.0|type_is:'dictionary' %} 14 | {# list of dicts #} 15 | 16 | 17 | {% else %} 18 | {# list of strings #} 19 | 20 | 30 | {% endif %} 31 | {% elif value|type_is:'dictionary' %} 32 | 33 | 34 | {% elif '_script' in key %} 35 | {# special case: show scripts in monospaced font #} 36 | 37 | {% elif 'icon_path' in key %} 38 | {% else %} 39 | {# regular scalar value #} 40 | 41 | {% endif %} 42 | {% endfor %} 43 | 44 |
{{ key }}{{ value }}
{{ key }}{{ value }}
{{ key }}{% include "catalogs/dict_list.html" with dict_list=value only %}
{{ key }} 21 | {% for item in value %} 22 | {% if 'catalog' in key %} 23 | {{ item }} 24 | {% else %} 25 | {{ item }} 26 | {% endif %} 27 | {% if not forloop.last %}
{% endif %} 28 | {% endfor %} 29 |
{{ key }}{% include "catalogs/generic_dict.html" with generic_dict=value only %}
{{ key }}{{ value }}
{{ key }}{{ value }}
45 | 46 | -------------------------------------------------------------------------------- /munkido/site_static/js/plugins/metisMenu/metisMenu.js: -------------------------------------------------------------------------------- 1 | /* 2 | * metismenu - v1.0.3 3 | * Easy menu jQuery plugin for Twitter Bootstrap 3 4 | * https://github.com/onokumus/metisMenu 5 | * 6 | * Made by Osman Nuri Okumuş 7 | * Under MIT License 8 | */ 9 | ;(function ($, window, document, undefined) { 10 | 11 | var pluginName = "metisMenu", 12 | defaults = { 13 | toggle: true 14 | }; 15 | 16 | function Plugin(element, options) { 17 | this.element = element; 18 | this.settings = $.extend({}, defaults, options); 19 | this._defaults = defaults; 20 | this._name = pluginName; 21 | this.init(); 22 | } 23 | 24 | Plugin.prototype = { 25 | init: function () { 26 | 27 | var $this = $(this.element), 28 | $toggle = this.settings.toggle; 29 | 30 | if (this.isIE() <= 9) { 31 | $this.find("li.active").has("ul").children("ul").collapse("show"); 32 | $this.find("li").not(".active").has("ul").children("ul").collapse("hide"); 33 | } else { 34 | $this.find("li.active").has("ul").children("ul").addClass("collapse in"); 35 | $this.find("li").not(".active").has("ul").children("ul").addClass("collapse"); 36 | } 37 | 38 | $this.find("li").has("ul").children("a").on("click", function (e) { 39 | e.preventDefault(); 40 | 41 | $(this).parent("li").toggleClass("active").children("ul").collapse("toggle"); 42 | 43 | if ($toggle) { 44 | $(this).parent("li").siblings().removeClass("active").children("ul.in").collapse("hide"); 45 | } 46 | }); 47 | }, 48 | 49 | isIE: function() {//https://gist.github.com/padolsey/527683 50 | var undef, 51 | v = 3, 52 | div = document.createElement("div"), 53 | all = div.getElementsByTagName("i"); 54 | 55 | while ( 56 | div.innerHTML = "", 57 | all[0] 58 | ) { 59 | return v > 4 ? v : undef; 60 | } 61 | } 62 | }; 63 | 64 | $.fn[ pluginName ] = function (options) { 65 | return this.each(function () { 66 | if (!$.data(this, "plugin_" + pluginName)) { 67 | $.data(this, "plugin_" + pluginName, new Plugin(this, options)); 68 | } 69 | }); 70 | }; 71 | 72 | })(jQuery, window, document); 73 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | # This is a standalone Dockerfile for Docker Hub. The Munki-Do git repository 2 | # has a Dockerfile in the root directory which does away with the need to clone the 3 | # docker-munki-do repository. So you normally won't need this one. 4 | 5 | # Use phusion/passenger-full as base image. To make your builds reproducible, make 6 | # sure you lock down to a specific version, not to `latest`! 7 | # See https://github.com/phusion/passenger-docker/blob/master/Changelog.md for 8 | # a list of version numbers. 9 | FROM phusion/passenger-full:0.9.17 10 | MAINTAINER Graham Pugh 11 | 12 | # Set correct environment variables. 13 | ENV HOME /root 14 | ENV DEBIAN_FRONTEND noninteractive 15 | ENV APP_DIR /home/app/munkido 16 | ENV TIME_ZONE America/New_York 17 | ENV APPNAME Munki-Do 18 | 19 | # Use baseimage-docker's init process. 20 | CMD ["/sbin/my_init"] 21 | 22 | # Install python 23 | RUN apt-get update && apt-get install -y \ 24 | openssh-server \ 25 | python-pip \ 26 | python-dev \ 27 | libpq-dev 28 | 29 | RUN git clone https://github.com/munki/munki.git /munki-tools 30 | RUN git clone https://github.com/grahampugh/munki-do.git $APP_DIR 31 | ADD django/requirements.txt $APP_DIR/ 32 | RUN pip install -r $APP_DIR/requirements.txt 33 | RUN touch /root/tmp.txt 34 | ADD django/ $APP_DIR/munkido/ 35 | RUN mkdir -p /var/log/django 36 | ADD nginx/munkido.conf /etc/nginx/sites-enabled/munkido.conf 37 | ADD run.sh /etc/my_init.d/run.sh 38 | RUN rm -f /etc/service/nginx/down 39 | RUN rm -f /etc/nginx/sites-enabled/default 40 | RUN groupadd munki 41 | RUN usermod -g munki app 42 | 43 | VOLUME ["/munki_repo", "/home/app/munkido" ] 44 | EXPOSE 8000 45 | 46 | # Uncomment the following lines to copy an ssh key to the Docker image 47 | # in order to allow passwordless `git push` 48 | # This is necessary in Bitbucket and should also work in Github 49 | # if you change the ssh-keyscan to `github.com`, so that you 50 | # don't have to pass passwords in plain text 51 | # You will need to add an `id_rsa` file to the same path as the Dockerfile, 52 | # as Docker cannot operate on files outside the current working directory. 53 | # To generate an SSH key, follow the instructions at: 54 | # https://confluence.atlassian.com/bitbucket/set-up-ssh-for-git-728138079.html 55 | # The id_rsa file will then be found at ~/.ssh 56 | 57 | ADD id_rsa /root/.ssh/id_rsa 58 | RUN touch /root/.ssh/known_hosts 59 | RUN chown root: /root/.ssh/id_rsa && chmod 600 /root/.ssh/id_rsa 60 | RUN ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts 61 | 62 | # Clean up APT when done. 63 | RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 64 | -------------------------------------------------------------------------------- /munkido/site_static/js/plugins/flot/jquery.flot.resize.js: -------------------------------------------------------------------------------- 1 | /* Flot plugin for automatically redrawing plots as the placeholder resizes. 2 | 3 | Copyright (c) 2007-2013 IOLA and Ole Laursen. 4 | Licensed under the MIT license. 5 | 6 | It works by listening for changes on the placeholder div (through the jQuery 7 | resize event plugin) - if the size changes, it will redraw the plot. 8 | 9 | There are no options. If you need to disable the plugin for some plots, you 10 | can just fix the size of their placeholders. 11 | 12 | */ 13 | 14 | /* Inline dependency: 15 | * jQuery resize event - v1.1 - 3/14/2010 16 | * http://benalman.com/projects/jquery-resize-plugin/ 17 | * 18 | * Copyright (c) 2010 "Cowboy" Ben Alman 19 | * Dual licensed under the MIT and GPL licenses. 20 | * http://benalman.com/about/license/ 21 | */ 22 | 23 | (function($,h,c){var a=$([]),e=$.resize=$.extend($.resize,{}),i,k="setTimeout",j="resize",d=j+"-special-event",b="delay",f="throttleWindow";e[b]=250;e[f]=true;$.event.special[j]={setup:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.add(l);$.data(this,d,{w:l.width(),h:l.height()});if(a.length===1){g()}},teardown:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.not(l);l.removeData(d);if(!a.length){clearTimeout(i)}},add:function(l){if(!e[f]&&this[k]){return false}var n;function m(s,o,p){var q=$(this),r=$.data(this,d);r.w=o!==c?o:q.width();r.h=p!==c?p:q.height();n.apply(this,arguments)}if($.isFunction(l)){n=l;return m}else{n=l.handler;l.handler=m}}};function g(){i=h[k](function(){a.each(function(){var n=$(this),m=n.width(),l=n.height(),o=$.data(this,d);if(m!==o.w||l!==o.h){n.trigger(j,[o.w=m,o.h=l])}});g()},e[b])}})(jQuery,this); 24 | 25 | (function ($) { 26 | var options = { }; // no options 27 | 28 | function init(plot) { 29 | function onResize() { 30 | var placeholder = plot.getPlaceholder(); 31 | 32 | // somebody might have hidden us and we can't plot 33 | // when we don't have the dimensions 34 | if (placeholder.width() == 0 || placeholder.height() == 0) 35 | return; 36 | 37 | plot.resize(); 38 | plot.setupGrid(); 39 | plot.draw(); 40 | } 41 | 42 | function bindEvents(plot, eventHolder) { 43 | plot.getPlaceholder().resize(onResize); 44 | } 45 | 46 | function shutdown(plot, eventHolder) { 47 | plot.getPlaceholder().unbind("resize", onResize); 48 | } 49 | 50 | plot.hooks.bindEvents.push(bindEvents); 51 | plot.hooks.shutdown.push(shutdown); 52 | } 53 | 54 | $.plot.plugins.push({ 55 | init: init, 56 | options: options, 57 | name: 'resize', 58 | version: '1.0' 59 | }); 60 | })(jQuery); -------------------------------------------------------------------------------- /manifests/templates/manifests/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load url from future %} 3 | 4 | {% block java_script %} 5 | {% load static %} 6 | 7 | {% endblock %} 8 | 9 | {% block data-source %}{{ manifest_list_json }}{% endblock %} 10 | {% block data-source-mobile %}{{ manifest_list_json }}{% endblock %} 11 | 12 | 13 | {% block page_title %}Manifests{% endblock %} 14 | 15 | {% block navbar-default_extensions %} 16 | {% if git_enabled %} 17 | {% endif %} 20 | {% endblock %} 21 | 22 | {% block content %} 23 |
24 | 41 | 66 |
67 |
68 |
69 |
70 |
71 | {% endblock %} 72 | 73 | -------------------------------------------------------------------------------- /docker/settings.py: -------------------------------------------------------------------------------- 1 | # Django settings for munki-do project. 2 | from django.conf import global_settings 3 | from system_settings import * 4 | from settings_import import ADMINS, TIME_ZONE, ALLOWED_HOSTS, GIT_PATH, GIT_IGNORE_PKGS, GIT_BRANCHING, PRODUCTION_BRANCH, MANIFEST_USERNAME_KEY, MANIFEST_USERNAME_IS_EDITABLE, MANIFEST_RESTRICTION_KEY, LOGIN_REDIRECT_URL, ALL_ITEMS 5 | 6 | # Override native makecatalogs with docker-installed path 7 | DEFAULT_MAKECATALOGS='/munki-tools/code/client/makecatalogs' 8 | 9 | # MUNKI_REPO_DIR holds the local filesystem path to the Munki repo 10 | MUNKI_REPO_DIR = '/munki_repo' 11 | 12 | USE_LDAP = False 13 | # LDAP authentication support 14 | if USE_LDAP: 15 | import ldap 16 | from django_auth_ldap.config import LDAPSearch, PosixGroupType 17 | 18 | # LDAP settings 19 | AUTH_LDAP_SERVER_URI = "ldap://foo.example.com" 20 | AUTH_LDAP_BIND_DN = "" 21 | AUTH_LDAP_BIND_PASSWORD = "" 22 | AUTH_LDAP_USER_SEARCH = LDAPSearch( 23 | "ou=People,o=ExampleCorp,c=US", 24 | ldap.SCOPE_SUBTREE, "(uid=%(user)s)") 25 | AUTH_LDAP_GROUP_SEARCH = LDAPSearch( 26 | "ou=Groups,o=ExampleCorp,c=US", 27 | ldap.SCOPE_SUBTREE, "(objectClass=posixGroup)") 28 | AUTH_LDAP_GROUP_TYPE = PosixGroupType() 29 | AUTH_LDAP_FIND_GROUP_PERMS = True 30 | AUTH_LDAP_USER_ATTR_MAP = {"first_name": "givenName", 31 | "last_name": "sn", 32 | "email": "mail"} 33 | # Cache group memberships for an hour to minimize LDAP traffic 34 | AUTH_LDAP_CACHE_GROUPS = True 35 | AUTH_LDAP_GROUP_CACHE_TIMEOUT = 3600 36 | 37 | if USE_LDAP: 38 | AUTHENTICATION_BACKENDS = ( 39 | 'django_auth_ldap.backend.LDAPBackend', 40 | 'django.contrib.auth.backends.ModelBackend', 41 | 'tokenapi.backends.TokenBackend', 42 | ) 43 | else: 44 | AUTHENTICATION_BACKENDS = ( 45 | 'django.contrib.auth.backends.ModelBackend', 46 | 'tokenapi.backends.TokenBackend', 47 | ) 48 | 49 | # using sqlite3 50 | DATABASES = { 51 | 'default': { 52 | 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. 53 | 'NAME': '/munki-do-db/munki-do.db', # Path to database file if using sqlite3. 54 | 'USER': '', # Not used with sqlite3. 55 | 'PASSWORD': '', # Not used with sqlite3. 56 | 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. 57 | 'PORT': '', # Set to empty string for default. Not used with sqlite3. 58 | } 59 | } 60 | 61 | # mysql example 62 | #DATABASES = { 63 | # 'default': { 64 | # 'ENGINE': 'django.db.backends.mysql', 65 | # 'NAME': 'munkiweb', 66 | # 'USER': 'munkiwebuser', 67 | # 'PASSWORD': 'munkiwebuserpasswd', 68 | # 'HOST': 'munkiwebdb.example.org', 69 | # 'PORT': '', 70 | # } 71 | #} 72 | 73 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # This Dockerfile is specifically for placement in the Munki-Do git repo. 2 | 3 | # Use phusion/passenger-full as base image. To make your builds reproducible, make 4 | # sure you lock down to a specific version, not to `latest`! 5 | # See https://github.com/phusion/passenger-docker/blob/master/Changelog.md for 6 | # a list of version numbers. 7 | FROM phusion/passenger-full:0.9.19 8 | MAINTAINER Graham Pugh 9 | 10 | # Set correct environment variables. 11 | ENV HOME /root 12 | ENV DEBIAN_FRONTEND noninteractive 13 | ENV APP_DIR /home/docker/munkido 14 | ENV APPNAME Munki-Do 15 | ENV DOCKER_MUNKIDO_TZ America/New_York 16 | # If GIT path is specified, git is enabled in Munki Do. 17 | # Provide an empty string to disable git. 18 | # ENV DOCKER_MUNKIDO_GIT_PATH = '/usr/bin/git' 19 | # If GIT_BRANCHING is set and the GIT path is specified above, 20 | # commits are pushed to a new branch. 21 | # ENV DOCKER_MUNKIDO_GIT_BRANCHING = 'yes' 22 | # If DOCKER_MUNKIDO_GIT_IGNORE_PKGS is set and the GIT path is specified above, 23 | # the 'pkgs' directory is not considered for git commit 24 | # ENV DOCKER_MUNKIDO_GIT_IGNORE_PKGS = 'yes' 25 | # If DOCKER_MUNKIDO_MANIFEST_RESTRICTION_KEY is set, 26 | # manifests are not restricted by group 27 | # ENV DOCKER_MUNKIDO_MANIFEST_RESTRICTION_KEY = 'restriction' 28 | 29 | # Use baseimage-docker's init process. 30 | CMD ["/sbin/my_init"] 31 | 32 | # Install python 33 | RUN apt-get update && apt-get install -y \ 34 | openssh-server \ 35 | python-pip \ 36 | python-dev \ 37 | libpq-dev 38 | 39 | RUN git clone https://github.com/munki/munki.git /munki-tools # force5 40 | ADD / $APP_DIR 41 | ADD docker/django/requirements.txt $APP_DIR/ 42 | RUN pip install -r $APP_DIR/requirements.txt 43 | ADD docker/settings.py $APP_DIR/munkido/ 44 | ADD docker/settings_import.py $APP_DIR/munkido/ 45 | ADD docker/django/ $APP_DIR/munkido/ 46 | RUN mkdir -p /var/log/django 47 | ADD docker/nginx/munkido.conf /etc/nginx/sites-enabled/munkido.conf 48 | ADD docker/run.sh /etc/my_init.d/run.sh 49 | RUN rm -f /etc/service/nginx/down 50 | RUN rm -f /etc/nginx/sites-enabled/default 51 | RUN groupadd munki 52 | RUN usermod -g munki app 53 | 54 | VOLUME ["/munki_repo", "/home/docker/munkido" ] 55 | EXPOSE 8000 56 | 57 | # Uncomment the following lines to copy an ssh key to the Docker image 58 | # in order to allow passwordless `git push` 59 | # This is necessary in Bitbucket, Github, Gitlab etc. 60 | # if you change the ssh-keyscan to the domain you are connecting to, so that you 61 | # don't have to pass passwords in plain text 62 | # You will need to add an `id_rsa` file to the same path as the Dockerfile, 63 | # as Docker cannot operate on files outside the current working directory. 64 | # To generate an SSH key, follow the instructions at: 65 | # https://confluence.atlassian.com/bitbucket/set-up-ssh-for-git-728138079.html 66 | # The id_rsa file will then be found at ~/.ssh 67 | 68 | ADD docker/id_rsa /root/.ssh/id_rsa 69 | RUN chown root: /root/.ssh/id_rsa && chmod 600 /root/.ssh/id_rsa 70 | ADD docker/known_hosts /root/.ssh/known_hosts 71 | 72 | # link django logs to stdout: 73 | RUN ln -sf /dev/stdout /var/log/django/info.log 74 | 75 | # Clean up APT when done. 76 | RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 77 | -------------------------------------------------------------------------------- /munkido/site_static/js/webadmin.js: -------------------------------------------------------------------------------- 1 | $.ajaxSetup({ 2 | beforeSend: function(xhr, settings) { 3 | if (settings.type == 'POST' || settings.type == 'PUT' || settings.type == 'DELETE') { 4 | function getCookie(name) { 5 | var cookieValue = null; 6 | if (document.cookie && document.cookie != '') { 7 | var cookies = document.cookie.split(';'); 8 | for (var i = 0; i < cookies.length; i++) { 9 | var cookie = jQuery.trim(cookies[i]); 10 | // Does this cookie string begin with the name we want? 11 | if (cookie.substring(0, name.length + 1) == (name + '=')) { 12 | cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); 13 | break; 14 | } 15 | } 16 | } 17 | return cookieValue; 18 | } 19 | if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) { 20 | // Only send the token to relative URLs i.e. locally. 21 | xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken')); 22 | } 23 | } 24 | } 25 | }); 26 | 27 | function setCookie(cname, cvalue, exdays) { 28 | var d = new Date(); 29 | d.setTime(d.getTime() + (exdays*24*60*60*1000)); 30 | var expires = "expires="+d.toUTCString(); 31 | document.cookie = cname + "=" + cvalue + "; " + expires; 32 | } 33 | 34 | function getCookie(cname) { 35 | var name = cname + "="; 36 | var ca = document.cookie.split(';'); 37 | for(var i=0; i 7 | 8 | {% endblock java_script %} 9 | 10 | {% block extra_style %} 11 | 12 | 13 | {% endblock %} 14 | 15 | {% block data-source %}{{ catalog_items }}{% endblock %} 16 | {% block data-source-mobile %}{{ catalog_items }}{% endblock %} 17 | 18 | 19 | {% block page_title %}Catalogs{% endblock %} 20 | 21 | {% block navbar-default_extensions %} 22 | 23 | 24 | {% if catalog_name == 'all' %} 25 | All items 26 | {% else %} 27 | {{ catalog_name }} 28 | {% endif %} 29 | 30 | 31 | 44 | 45 | {% endblock %} 46 | 47 | {% block content %} 48 |
49 |
50 | {% if catalog_name %} 51 | {% if catalog %} 52 |
53 |
54 | {% regroup catalog|dictsort:'display_name' by name as catalog_items %} 55 | {% for item_name in catalog_items %} 56 | {% with item_name.list|dictsortreversed:'version' as item_list %} 57 | 58 | {{ item_list.0.display_name }} 59 | 60 | {% endwith %} 61 | {% endfor %} 62 |
63 |
64 | {% else %} 65 |

Catalog {{ catalog_name }} is empty.

66 | {% endif %} 67 | {% endif %} 68 |
69 |
70 |
71 | {% for item_name in catalog_items %} 72 | {% with item_name.list|dictsortreversed:'version' as item_list %} 73 | 83 | {% endwith %} 84 | {% endfor %} 85 |
86 |
87 | 88 |
89 |
90 |
91 | {% endblock content %} 92 | -------------------------------------------------------------------------------- /munkido/templates/registration/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {% load static %} 8 | 9 | 10 | 24 | 25 | {% block extra_style %}{% endblock %} 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | {% block java_script %}{% endblock %} 35 | 36 | Munki-Do 37 | 38 | 39 | {% load url from future %} 40 | {% block content %} 41 |
42 | 43 | 67 |
68 | {% endblock %} 69 | -------------------------------------------------------------------------------- /catalogs/models.py: -------------------------------------------------------------------------------- 1 | import os 2 | import plistlib 3 | 4 | from django.conf import settings 5 | from django.db import models 6 | 7 | REPO_DIR = settings.MUNKI_REPO_DIR 8 | STATIC_URL = settings.STATIC_URL 9 | MEDIA_URL = settings.MEDIA_URL 10 | ICONS_DIR = settings.ICONS_DIR 11 | 12 | class Catalog(object): 13 | @classmethod 14 | def list(self): 15 | '''Returns a list of available catalogs, which is a list 16 | of catalog names (strings)''' 17 | catalogs_path = os.path.join(REPO_DIR, 'catalogs') 18 | catalogs = [] 19 | for name in os.listdir(catalogs_path): 20 | if name.startswith("._") or name == ".DS_Store": 21 | # don't process these 22 | continue 23 | try: 24 | catalog = plistlib.readPlist(os.path.join(catalogs_path, name)) 25 | except Exception: 26 | # skip items that aren't valid plists 27 | pass 28 | else: 29 | catalogs.append(name) 30 | return catalogs 31 | 32 | 33 | @classmethod 34 | def detail(self, catalog_name): 35 | '''Gets the contents of a catalog, which is a list 36 | of pkginfo items''' 37 | catalog_path = os.path.join( 38 | REPO_DIR, 'catalogs', catalog_name) 39 | if os.path.exists(catalog_path): 40 | try: 41 | catalog_items = plistlib.readPlist(catalog_path) 42 | index = 0 43 | for item in catalog_items: 44 | item['index'] = index 45 | index += 1 46 | return catalog_items 47 | except Exception, errmsg: 48 | return None 49 | else: 50 | return None 51 | 52 | 53 | @classmethod 54 | def item_detail(self, catalog_name, item_index): 55 | '''Returns detail for a single catalog item''' 56 | catalog_path = os.path.join( 57 | REPO_DIR, 'catalogs', catalog_name) 58 | if os.path.exists(catalog_path): 59 | try: 60 | catalog_items = plistlib.readPlist(catalog_path) 61 | return catalog_items[int(item_index)] 62 | except Exception, errmsg: 63 | return None 64 | else: 65 | return None 66 | 67 | 68 | @classmethod 69 | def getValidInstallItems(self, catalog_list): 70 | '''Returns a list of valid install item names for the 71 | list of catalogs''' 72 | install_items = set() 73 | for catalog in catalog_list: 74 | catalog_items = Catalog.detail(catalog) 75 | catalog_item_names = list(set( 76 | [item['name'] for item in catalog_items])) 77 | install_items.update(catalog_item_names) 78 | catalog_item_names_with_versions = list(set( 79 | [item['name'] + '-' + trimVersionString(item['version']) 80 | for item in catalog_items])) 81 | install_items.update(catalog_item_names_with_versions) 82 | return list(install_items) 83 | 84 | @classmethod 85 | def get_icon(self, item_name): 86 | if not item_name.endswith(('.png', '.jpg', '.jpeg')): 87 | item_name = item_name + ".png" 88 | icons_path = os.path.join(os.path.join(REPO_DIR, ICONS_DIR), item_name) 89 | default_icon = STATIC_URL + 'img/PackageIcon.png' 90 | item_icon = MEDIA_URL + item_name 91 | if os.path.exists(icons_path): 92 | return item_icon 93 | else: 94 | return default_icon 95 | 96 | class Catalogs(models.Model): 97 | class Meta: 98 | permissions = (("can_view_catalogs", "Can view catalogs"),) -------------------------------------------------------------------------------- /catalogs/static/js/bootstrap-tabdrop.js: -------------------------------------------------------------------------------- 1 | /* ========================================================= 2 | * bootstrap-tabdrop.js 3 | * http://www.eyecon.ro/bootstrap-tabdrop 4 | * ========================================================= 5 | * Copyright 2012 Stefan Petre 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ========================================================= */ 19 | 20 | !function( $ ) { 21 | 22 | var WinReszier = (function(){ 23 | var registered = []; 24 | var inited = false; 25 | var timer; 26 | var resize = function(ev) { 27 | clearTimeout(timer); 28 | timer = setTimeout(notify, 100); 29 | }; 30 | var notify = function() { 31 | for(var i=0, cnt=registered.length; i'+options.text+' ') 57 | .prependTo(this.element); 58 | if (this.element.parent().is('.tabs-below')) { 59 | this.dropdown.addClass('dropup'); 60 | } 61 | WinReszier.register($.proxy(this.layout, this)); 62 | this.layout(); 63 | }; 64 | 65 | TabDrop.prototype = { 66 | constructor: TabDrop, 67 | 68 | layout: function() { 69 | var collection = []; 70 | this.dropdown.removeClass('hide'); 71 | this.element 72 | .append(this.dropdown.find('li')) 73 | .find('>li') 74 | .not('.tabdrop') 75 | .each(function(){ 76 | if(this.offsetTop > 0) { 77 | collection.push(this); 78 | } 79 | }); 80 | if (collection.length > 0) { 81 | collection = $(collection); 82 | this.dropdown 83 | .find('ul') 84 | .empty() 85 | .append(collection); 86 | if (this.dropdown.find('.active').length == 1) { 87 | this.dropdown.addClass('active'); 88 | } else { 89 | this.dropdown.removeClass('active'); 90 | } 91 | } else { 92 | this.dropdown.addClass('hide'); 93 | } 94 | } 95 | } 96 | 97 | $.fn.tabdrop = function ( option ) { 98 | return this.each(function () { 99 | var $this = $(this), 100 | data = $this.data('tabdrop'), 101 | options = typeof option === 'object' && option; 102 | if (!data) { 103 | $this.data('tabdrop', (data = new TabDrop(this, $.extend({}, $.fn.tabdrop.defaults,options)))); 104 | } 105 | if (typeof option == 'string') { 106 | data[option](); 107 | } 108 | }) 109 | }; 110 | 111 | $.fn.tabdrop.defaults = { 112 | text: '' 113 | }; 114 | 115 | $.fn.tabdrop.Constructor = TabDrop; 116 | 117 | }( window.jQuery ); -------------------------------------------------------------------------------- /munkido/site_static/js/plugins/flot/jquery.flot.tooltip.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jquery.flot.tooltip 3 | * 4 | * description: easy-to-use tooltips for Flot charts 5 | * version: 0.6.2 6 | * author: Krzysztof Urbas @krzysu [myviews.pl] 7 | * website: https://github.com/krzysu/flot.tooltip 8 | * 9 | * build on 2013-09-30 10 | * released under MIT License, 2012 11 | */ 12 | (function(t){var o={tooltip:!1,tooltipOpts:{content:"%s | X: %x | Y: %y",xDateFormat:null,yDateFormat:null,shifts:{x:10,y:20},defaultTheme:!0,onHover:function(){}}},i=function(t){this.tipPosition={x:0,y:0},this.init(t)};i.prototype.init=function(o){function i(t){var o={};o.x=t.pageX,o.y=t.pageY,s.updateTooltipPosition(o)}function e(t,o,i){var e=s.getDomElement();if(i){var n;n=s.stringFormat(s.tooltipOptions.content,i),e.html(n),s.updateTooltipPosition({x:o.pageX,y:o.pageY}),e.css({left:s.tipPosition.x+s.tooltipOptions.shifts.x,top:s.tipPosition.y+s.tooltipOptions.shifts.y}).show(),"function"==typeof s.tooltipOptions.onHover&&s.tooltipOptions.onHover(i,e)}else e.hide().html("")}var s=this;o.hooks.bindEvents.push(function(o,n){s.plotOptions=o.getOptions(),s.plotOptions.tooltip!==!1&&void 0!==s.plotOptions.tooltip&&(s.tooltipOptions=s.plotOptions.tooltipOpts,s.getDomElement(),t(o.getPlaceholder()).bind("plothover",e),t(n).bind("mousemove",i))}),o.hooks.shutdown.push(function(o,s){t(o.getPlaceholder()).unbind("plothover",e),t(s).unbind("mousemove",i)})},i.prototype.getDomElement=function(){var o;return t("#flotTip").length>0?o=t("#flotTip"):(o=t("
").attr("id","flotTip"),o.appendTo("body").hide().css({position:"absolute"}),this.tooltipOptions.defaultTheme&&o.css({background:"#fff","z-index":"100",padding:"0.4em 0.6em","border-radius":"0.5em","font-size":"0.8em",border:"1px solid #111",display:"none","white-space":"nowrap"})),o},i.prototype.updateTooltipPosition=function(o){var i=t("#flotTip").outerWidth()+this.tooltipOptions.shifts.x,e=t("#flotTip").outerHeight()+this.tooltipOptions.shifts.y;o.x-t(window).scrollLeft()>t(window).innerWidth()-i&&(o.x-=i),o.y-t(window).scrollTop()>t(window).innerHeight()-e&&(o.y-=e),this.tipPosition.x=o.x,this.tipPosition.y=o.y},i.prototype.stringFormat=function(t,o){var i=/%p\.{0,1}(\d{0,})/,e=/%s/,s=/%x\.{0,1}(?:\d{0,})/,n=/%y\.{0,1}(?:\d{0,})/;return"function"==typeof t&&(t=t(o.series.label,o.series.data[o.dataIndex][0],o.series.data[o.dataIndex][1],o)),o.series.percent!==void 0&&(t=this.adjustValPrecision(i,t,o.series.percent)),o.series.label!==void 0&&(t=t.replace(e,o.series.label)),this.isTimeMode("xaxis",o)&&this.isXDateFormat(o)&&(t=t.replace(s,this.timestampToDate(o.series.data[o.dataIndex][0],this.tooltipOptions.xDateFormat))),this.isTimeMode("yaxis",o)&&this.isYDateFormat(o)&&(t=t.replace(n,this.timestampToDate(o.series.data[o.dataIndex][1],this.tooltipOptions.yDateFormat))),"number"==typeof o.series.data[o.dataIndex][0]&&(t=this.adjustValPrecision(s,t,o.series.data[o.dataIndex][0])),"number"==typeof o.series.data[o.dataIndex][1]&&(t=this.adjustValPrecision(n,t,o.series.data[o.dataIndex][1])),o.series.xaxis.tickFormatter!==void 0&&(t=t.replace(s,o.series.xaxis.tickFormatter(o.series.data[o.dataIndex][0],o.series.xaxis))),o.series.yaxis.tickFormatter!==void 0&&(t=t.replace(n,o.series.yaxis.tickFormatter(o.series.data[o.dataIndex][1],o.series.yaxis))),t},i.prototype.isTimeMode=function(t,o){return o.series[t].options.mode!==void 0&&"time"===o.series[t].options.mode},i.prototype.isXDateFormat=function(){return this.tooltipOptions.xDateFormat!==void 0&&null!==this.tooltipOptions.xDateFormat},i.prototype.isYDateFormat=function(){return this.tooltipOptions.yDateFormat!==void 0&&null!==this.tooltipOptions.yDateFormat},i.prototype.timestampToDate=function(o,i){var e=new Date(o);return t.plot.formatDate(e,i)},i.prototype.adjustValPrecision=function(t,o,i){var e,s=o.match(t);return null!==s&&""!==RegExp.$1&&(e=RegExp.$1,i=i.toFixed(e),o=o.replace(t,i)),o};var e=function(t){new i(t)};t.plot.plugins.push({init:e,options:o,name:"tooltip",version:"0.6.1"})})(jQuery); -------------------------------------------------------------------------------- /docker/settings_import.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | from os import getenv 3 | import locale 4 | from system_settings import * 5 | 6 | 7 | # Read the list of allowed hosts from the $DOCKER_MUNKIDO_ALLOWED_HOSTS env var, or 8 | # allow all hosts if none was set. 9 | if getenv('DOCKER_MUNKIDO_ALLOWED_HOSTS'): 10 | ALLOWED_HOSTS = getenv('DOCKER_MUNKIDO_ALLOWED_HOSTS').split(',') 11 | else: 12 | ALLOWED_HOSTS = ['*'] 13 | 14 | 15 | # Read list of admins from $DOCKER_MUNKIDO_ADMINS env var 16 | admin_list = [] 17 | if getenv('DOCKER_MUNKIDO_ADMINS'): 18 | admins_var = getenv('DOCKER_MUNKIDO_ADMINS') 19 | if ',' in admins_var and ':' in admins_var: 20 | for admin in admins_var.split(':'): 21 | admin_list.append(tuple(admin.split(','))) 22 | ADMINS = tuple(admin_list) 23 | elif ',' in admins_var: 24 | admin_list.append(tuple(admins_var.split(','))) 25 | ADMINS = tuple(admin_list) 26 | else: 27 | ADMINS = ( 28 | ('Admin User', 'admin@test.com') 29 | ) 30 | 31 | 32 | # Read the preferred time zone from $DOCKER_SAL_TZ, use system locale or 33 | # set to 'America/New_York' if neither are set 34 | if getenv('DOCKER_MUNKIDO_TZ'): 35 | if '/' in getenv('DOCKER_MUNKIDO_TZ'): 36 | TIME_ZONE = getenv('DOCKER_MUNKIDO_TZ') 37 | else: TIME_ZONE = 'America/New_York' 38 | # elif getenv('TZ'): 39 | # TIME_ZONE = getenv('TZ') 40 | # else: 41 | # TIME_ZONE = 'America/New_York' 42 | 43 | 44 | # Read the default start URL from $DOCKER_MUNKIDO_LOGIN_REDIRECT_URL env var, or 45 | # set to '/catalog' as default 46 | if getenv('DOCKER_MUNKIDO_LOGIN_REDIRECT_URL'): 47 | LOGIN_REDIRECT_URL = getenv('DOCKER_MUNKIDO_LOGIN_REDIRECT_URL') 48 | else: 49 | LOGIN_REDIRECT_URL='/catalog' 50 | 51 | 52 | # Read the $DOCKER_MUNKIDO_ALL_ITEMS env var, or 53 | # set to False as default 54 | # if true all software packages are shown in autocompletion not only the one in included catalogs 55 | if getenv('DOCKER_MUNKIDO_ALL_ITEMS'): 56 | ALL_ITEMS = getenv('DOCKER_MUNKIDO_ALL_ITEMS') 57 | else: 58 | ALL_ITEMS=False 59 | 60 | 61 | # Read the path to git from the $DOCKER_MUNKIDO_GIT_PATH env var, or 62 | # specify an empty git path, which disables git 63 | if getenv('DOCKER_MUNKIDO_GIT_PATH'): 64 | GIT_PATH = getenv('DOCKER_MUNKIDO_GIT_PATH') 65 | else: 66 | GIT_PATH = '' 67 | 68 | 69 | # Read the $DOCKER_MUNKIDO_GIT_IGNORE_PKGS env var, or 70 | # specify an empty string, which means the pkgs folder is *not* ignored 71 | if getenv('DOCKER_MUNKIDO_GIT_IGNORE_PKGS'): 72 | GIT_IGNORE_PKGS = getenv('DOCKER_MUNKIDO_GIT_IGNORE_PKGS') 73 | else: 74 | GIT_IGNORE_PKGS = '' 75 | 76 | 77 | # Read the $DOCKER_MUNKIDO_GIT_BRANCHING env var, or 78 | # specify an empty string, which means git branching is *not* enabled 79 | if getenv('DOCKER_MUNKIDO_GIT_BRANCHING'): 80 | GIT_BRANCHING = getenv('DOCKER_MUNKIDO_GIT_BRANCHING') 81 | else: 82 | GIT_BRANCHING = '' 83 | 84 | 85 | # Read the $DOCKER_MUNKIDO_PRODUCTION_BRANCH env var, or 86 | # specify 'master' as default 87 | if getenv('DOCKER_MUNKIDO_PRODUCTION_BRANCH'): 88 | PRODUCTION_BRANCH = getenv('DOCKER_MUNKIDO_PRODUCTION_BRANCH') 89 | else: 90 | PRODUCTION_BRANCH = 'master' 91 | 92 | 93 | # Read the $DOCKER_MUNKIDO_MANIFEST_USERNAME_KEY env var, or 94 | # specify 'user' as default (this is not yet enabled) 95 | if getenv('DOCKER_MUNKIDO_MANIFEST_USERNAME_KEY'): 96 | MANIFEST_USERNAME_KEY = getenv('DOCKER_MUNKIDO_MANIFEST_USERNAME_KEY') 97 | else: 98 | MANIFEST_USERNAME_KEY = 'user' 99 | 100 | # Read the $DOCKER_MUNKIDO_MANIFEST_RESTRICTION_KEY env var, or 101 | # specify '' as default (which disables manifest restriction) 102 | # To enable, set as 'restriction' 103 | if getenv('DOCKER_MUNKIDO_MANIFEST_RESTRICTION_KEY'): 104 | MANIFEST_RESTRICTION_KEY = getenv('DOCKER_MUNKIDO_MANIFEST_RESTRICTION_KEY') 105 | else: 106 | MANIFEST_RESTRICTION_KEY = '' 107 | 108 | 109 | # Read the $DOCKER_MUNKIDO_MANIFEST_USERNAME_IS_EDITABLE env var, or 110 | # specify False as default (user editing is not yet enabled anyway) 111 | if getenv('DOCKER_MUNKIDO_MANIFEST_USERNAME_IS_EDITABLE'): 112 | MANIFEST_USERNAME_IS_EDITABLE = getenv('DOCKER_MUNKIDO_MANIFEST_USERNAME_IS_EDITABLE') 113 | else: 114 | MANIFEST_USERNAME_IS_EDITABLE = False 115 | 116 | 117 | -------------------------------------------------------------------------------- /pkgs/templates/pkgs/confirm.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | 4 | {% block page_title %}Packages{% endblock %} 5 | 6 | {% block navbar-default_extensions %} 7 |
8 | {% if confirm_move %} 9 |

Confirm Move Packages

10 | {% elif confirm_add %} 11 |

Confirm add Packages to Catalog

12 | {% elif confirm_remove %} 13 |

Confirm remove Packages from Catalog

14 | {% else %} 15 |

Confirm Delete Packages

16 | {% endif %} 17 |
18 | {% endblock %} 19 | 20 | {% block content %} 21 | 22 | {% if items_to_move %} 23 | 24 | {% if confirm_delete or confirm_delete_pkgs %} 25 |
26 | {% else %} 27 | 28 | {% endif %} 29 | {% csrf_token %} 30 |
31 | {% if dest_catalog == "set-new" %} 32 | Enter a new catalog name:   33 | 34 | {% endif %} 35 | {% if confirm_move %} 36 | 37 | {% elif confirm_add %} 38 | 39 | {% elif confirm_remove %} 40 | 41 | {% elif confirm_delete_pkgs %} 42 | 43 | {% else %} 44 | 45 | {% endif %} 46 |
47 |

48 | 49 | 50 | 51 | {% if confirm_remove or confirm_delete or confirm_add or confirm_move %} 52 | 53 | 54 | {% endif %} 55 | {% if confirm_remove %} 56 | 57 | {% endif %} 58 | {% if confirm_delete or confirm_delete_pkgs %} 59 | 60 | {% endif %} 61 | {% if confirm_add or confirm_move %} 62 | 63 | {% endif %} 64 | 65 | 66 | 67 | {% if confirm_delete_pkgs %} 68 | {% for pkg_location in items_to_move %} 69 | 70 | 73 | 74 | {% endfor %} 75 | {% else %} 76 | {% for package, version, orig_catalog, pkg_location in items_to_move %} 77 | {% if confirm_move and orig_catalog != dest_catalog %} 78 | 79 | 82 | 83 | 90 | 91 | {% elif confirm_add and orig_catalog != dest_catalog %} 92 | 93 | 96 | 97 | 104 | 105 | {% elif confirm_remove %} 106 | 107 | 109 | 110 | 111 | 112 | {% else %} 113 | 114 | 116 | 117 | 118 | 119 | {% endif %} 120 | {% endfor %} 121 | {% endif %} 122 | 123 |
NameVersionOrigin Catalog(s)Package LocationNew Catalog
71 | 72 | {{ pkg_location }}
80 | 81 | {{ package }}{{ version }} 84 | {% if dest_catalog = 'set-new' %} 85 | (Input new catalog above) 86 | {% else %} 87 | {{ dest_catalog }} 88 | {% endif %} 89 |
94 | 95 | {{ package }}{{ version }} 98 | {% if dest_catalog = 'set-new' %} 99 | (Input new catalog above) 100 | {% else %} 101 | {{ dest_catalog }} 102 | {% endif %} 103 |
108 | {{ package }}{{ version }}{{ orig_catalog }}
115 | {{ package }}{{ version }}{{ pkg_location }}
124 |

125 | {% else %} 126 |

No Packages selected.

127 | {% endif %} 128 | {% endblock content %} 129 | -------------------------------------------------------------------------------- /munkido/site_static/css/plugins/timeline.css: -------------------------------------------------------------------------------- 1 | .timeline { 2 | position: relative; 3 | padding: 20px 0 20px; 4 | list-style: none; 5 | } 6 | 7 | .timeline:before { 8 | content: " "; 9 | position: absolute; 10 | top: 0; 11 | bottom: 0; 12 | left: 50%; 13 | width: 3px; 14 | margin-left: -1.5px; 15 | background-color: #eeeeee; 16 | } 17 | 18 | .timeline > li { 19 | position: relative; 20 | margin-bottom: 20px; 21 | } 22 | 23 | .timeline > li:before, 24 | .timeline > li:after { 25 | content: " "; 26 | display: table; 27 | } 28 | 29 | .timeline > li:after { 30 | clear: both; 31 | } 32 | 33 | .timeline > li:before, 34 | .timeline > li:after { 35 | content: " "; 36 | display: table; 37 | } 38 | 39 | .timeline > li:after { 40 | clear: both; 41 | } 42 | 43 | .timeline > li > .timeline-panel { 44 | float: left; 45 | position: relative; 46 | width: 46%; 47 | padding: 20px; 48 | border: 1px solid #d4d4d4; 49 | border-radius: 2px; 50 | -webkit-box-shadow: 0 1px 6px rgba(0,0,0,0.175); 51 | box-shadow: 0 1px 6px rgba(0,0,0,0.175); 52 | } 53 | 54 | .timeline > li > .timeline-panel:before { 55 | content: " "; 56 | display: inline-block; 57 | position: absolute; 58 | top: 26px; 59 | right: -15px; 60 | border-top: 15px solid transparent; 61 | border-right: 0 solid #ccc; 62 | border-bottom: 15px solid transparent; 63 | border-left: 15px solid #ccc; 64 | } 65 | 66 | .timeline > li > .timeline-panel:after { 67 | content: " "; 68 | display: inline-block; 69 | position: absolute; 70 | top: 27px; 71 | right: -14px; 72 | border-top: 14px solid transparent; 73 | border-right: 0 solid #fff; 74 | border-bottom: 14px solid transparent; 75 | border-left: 14px solid #fff; 76 | } 77 | 78 | .timeline > li > .timeline-badge { 79 | z-index: 100; 80 | position: absolute; 81 | top: 16px; 82 | left: 50%; 83 | width: 50px; 84 | height: 50px; 85 | margin-left: -25px; 86 | border-radius: 50% 50% 50% 50%; 87 | text-align: center; 88 | font-size: 1.4em; 89 | line-height: 50px; 90 | color: #fff; 91 | background-color: #999999; 92 | } 93 | 94 | .timeline > li.timeline-inverted > .timeline-panel { 95 | float: right; 96 | } 97 | 98 | .timeline > li.timeline-inverted > .timeline-panel:before { 99 | right: auto; 100 | left: -15px; 101 | border-right-width: 15px; 102 | border-left-width: 0; 103 | } 104 | 105 | .timeline > li.timeline-inverted > .timeline-panel:after { 106 | right: auto; 107 | left: -14px; 108 | border-right-width: 14px; 109 | border-left-width: 0; 110 | } 111 | 112 | .timeline-badge.primary { 113 | background-color: #2e6da4 !important; 114 | } 115 | 116 | .timeline-badge.success { 117 | background-color: #3f903f !important; 118 | } 119 | 120 | .timeline-badge.warning { 121 | background-color: #f0ad4e !important; 122 | } 123 | 124 | .timeline-badge.danger { 125 | background-color: #d9534f !important; 126 | } 127 | 128 | .timeline-badge.info { 129 | background-color: #5bc0de !important; 130 | } 131 | 132 | .timeline-title { 133 | margin-top: 0; 134 | color: inherit; 135 | } 136 | 137 | .timeline-body > p, 138 | .timeline-body > ul { 139 | margin-bottom: 0; 140 | } 141 | 142 | .timeline-body > p + p { 143 | margin-top: 5px; 144 | } 145 | 146 | @media(max-width:767px) { 147 | ul.timeline:before { 148 | left: 40px; 149 | } 150 | 151 | ul.timeline > li > .timeline-panel { 152 | width: calc(100% - 90px); 153 | width: -moz-calc(100% - 90px); 154 | width: -webkit-calc(100% - 90px); 155 | } 156 | 157 | ul.timeline > li > .timeline-badge { 158 | top: 16px; 159 | left: 15px; 160 | margin-left: 0; 161 | } 162 | 163 | ul.timeline > li > .timeline-panel { 164 | float: right; 165 | } 166 | 167 | ul.timeline > li > .timeline-panel:before { 168 | right: auto; 169 | left: -15px; 170 | border-right-width: 15px; 171 | border-left-width: 0; 172 | } 173 | 174 | ul.timeline > li > .timeline-panel:after { 175 | right: auto; 176 | left: -14px; 177 | border-right-width: 14px; 178 | border-left-width: 0; 179 | } 180 | } -------------------------------------------------------------------------------- /catalogs/views.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from django.template import RequestContext 3 | from django.core.context_processors import csrf 4 | from django.shortcuts import render_to_response 5 | from django.contrib.auth.decorators import login_required, permission_required 6 | from django.contrib.auth.models import Permission 7 | from django.contrib.auth.models import User 8 | from models import Catalog 9 | from django.utils.datastructures import SortedDict 10 | 11 | import json 12 | 13 | def nameAndVersion(aString): 14 | ### from munkilib.updatecheck 15 | """Splits a string into the name and version number. 16 | 17 | Name and version must be seperated with a hyphen ('-') 18 | or double hyphen ('--'). 19 | 'TextWrangler-2.3b1' becomes ('TextWrangler', '2.3b1') 20 | 'AdobePhotoshopCS3--11.2.1' becomes ('AdobePhotoshopCS3', '11.2.1') 21 | 'MicrosoftOffice2008-12.2.1' becomes ('MicrosoftOffice2008', '12.2.1') 22 | """ 23 | for delim in ('--', '-'): 24 | if aString.count(delim) > 0: 25 | chunks = aString.split(delim) 26 | vers = chunks.pop() 27 | name = delim.join(chunks) 28 | if vers[0] in '0123456789': 29 | return (name, vers) 30 | 31 | return (aString, '') 32 | 33 | 34 | def trimVersionString(version_string): 35 | ### from munkilib.updatecheck 36 | """Trims all lone trailing zeros in the version string after major/minor. 37 | 38 | Examples: 39 | 10.0.0.0 -> 10.0 40 | 10.0.0.1 -> 10.0.0.1 41 | 10.0.0-abc1 -> 10.0.0-abc1 42 | 10.0.0-abc1.0 -> 10.0.0-abc1 43 | """ 44 | if version_string == None or version_string == '': 45 | return '' 46 | version_parts = version_string.split('.') 47 | # strip off all trailing 0's in the version, while over 2 parts. 48 | while len(version_parts) > 2 and version_parts[-1] == '0': 49 | del(version_parts[-1]) 50 | return '.'.join(version_parts) 51 | 52 | 53 | @login_required 54 | @permission_required('catalogs.can_view_catalogs', login_url='/login/') 55 | def item_detail(request, catalog_name, item_index): 56 | catalog_item = Catalog.item_detail(catalog_name, item_index) 57 | featured_keys = ['name', 'version', 'display_name', 58 | 'description', 'catalogs', 'icon_name'] 59 | 60 | # get icon 61 | if not "icon_name" in catalog_item: 62 | catalog_item["icon_name"] = "" 63 | 64 | # sort the item by key so keys are displayed 65 | # in expected order 66 | sorted_dict = SortedDict() 67 | for key in featured_keys: 68 | if key in catalog_item: 69 | sorted_dict[key] = catalog_item[key] 70 | key_list = catalog_item.keys() 71 | key_list.sort() 72 | for key in key_list: 73 | if key not in featured_keys: 74 | sorted_dict[key] = catalog_item[key] 75 | 76 | c = RequestContext(request,{'catalog_item': sorted_dict}) 77 | c.update(csrf(request)) 78 | return render_to_response('catalogs/item_detail.html', c) 79 | 80 | 81 | @login_required 82 | @permission_required('catalogs.can_view_catalogs', login_url='/login/') 83 | def catalog_view(request, catalog_name=None, item_index=None): 84 | catalog_list = Catalog.list() 85 | if request.is_ajax(): 86 | return HttpResponse(json.dumps(catalog_list), 87 | mimetype='application/json') 88 | catalog = None 89 | catalog_item = None 90 | if not catalog_name: 91 | catalog_name = "all" 92 | 93 | catalog = Catalog.detail(catalog_name) 94 | 95 | catalog_items = list() 96 | for item in catalog: 97 | if 'display_name' not in item: 98 | item['display_name'] = item['name'] 99 | if item.display_name not in catalog_items: 100 | catalog_items.append(item.display_name) 101 | catalog_items_json = json.dumps(catalog_items) 102 | 103 | if item_index: 104 | catalog_item = Catalog.item_detail(catalog_name, item_index) 105 | 106 | # get icon 107 | counter = 0 108 | for item in catalog: 109 | if "icon_name" in item: 110 | icon = Catalog.get_icon(item.icon_name) 111 | else: 112 | icon = Catalog.get_icon(item.name) 113 | catalog[counter].icon_name = icon 114 | counter += 1 115 | 116 | c = RequestContext(request,{'catalog_list': catalog_list, 117 | 'catalog_name': catalog_name, 118 | 'catalog': catalog, 119 | 'item_index': item_index, 120 | 'catalog_item': catalog_item, 121 | 'catalog_items': catalog_items_json, 122 | 'user': request.user, 123 | 'page': 'catalogs'}) 124 | c.update(csrf(request)) 125 | return render_to_response('catalogs/catalog.html', c) 126 | 127 | -------------------------------------------------------------------------------- /pkgs/templates/pkgs/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block java_script %} 4 | {% load static %} 5 | 6 | {% endblock java_script %} 7 | 8 | 9 | {% block page_title %}Packages{% endblock %} 10 | 11 | {% block navbar-default_extensions %} 12 | {% if git_enabled %} 13 |
14 | 17 | {% if user.is_staff or user.is_superuser%} 18 | 21 | {% endif %} 22 |
23 | {% endif %} 24 | 25 | 26 | 27 | 28 | {% if catalog_filter == 'all' %} 29 | All items 30 | {% else %} 31 | {{ catalog_filter|default_if_none:"All items" }} 32 | {% endif %} 33 | 34 | 35 | 48 | 49 | {% endblock %} 50 | 51 | {% block content %} 52 | {# Filter packages #} 53 | 54 |
55 |
56 | 61 | 62 | Hint: you can use shell-style wildcards in searches for 'fuzzy' matches. 63 |
64 |
65 | 66 | {% if all_catalog_items %} 67 | 68 | {# Drop-down list for moving to a catalog #} 69 | 70 |
71 | {% csrf_token %} 72 | {% if change_pkgs or delete_pkgs %} 73 |
74 | {% if change_pkgs %} 75 |
76 | 77 | 78 |
79 | 87 |  or  88 | 89 |      90 | {% endif %} 91 | {% if delete_pkgs %} 92 | 93 | {% endif %} 94 |
95 | {% endif %} 96 | 97 |

98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | {% if change_pkgs or delete_pkgs %} 106 | 107 | {% endif %} 108 | 109 | 110 | 111 | {% for pkg in all_catalog_items %} 112 | 113 | 114 | 115 | 122 | 123 | {% if change_pkgs or delete_pkgs %} 124 | 131 | {% endif %} 132 | 133 | {% endfor %} 134 | 135 |
NameVersionCatalog(s)Package locationToggle All
{{ pkg.name }}{{ pkg.version }} 116 | {% for catalog in pkg.catalogs %} 117 | {{ catalog }}
118 | {% empty %} 119 | (No catalog)
120 | {% endfor %} 121 |
{{ pkg.installer_item_location }} 125 | {% for catalog in pkg.catalogs %} 126 |
127 | {% empty %} 128 |
129 | {% endfor %} 130 |
136 |

137 | {% else %} 138 |

There are no Packages in your repository!

139 | {% endif %} 140 | {% endblock content %} -------------------------------------------------------------------------------- /munkido/site_static/css/bootstrapxl.css: -------------------------------------------------------------------------------- 1 | /* 2 | * CSS file with Bootstrap grid classes for screens bigger than 1600px. Just add this file after the Bootstrap CSS file and you will be able to juse col-xl, col-xl-push, hidden-xl, etc. 3 | * 4 | * Author: Marc van Nieuwenhuijzen 5 | * Company: WebVakman 6 | * Site: WebVakman.nl 7 | * 8 | */ 9 | 10 | .visible-xl-block, 11 | .visible-xl-inline, 12 | .visible-xl-inline-block, 13 | .visible-xl{ 14 | display: none !important; 15 | } 16 | 17 | @media (min-width: 2080px) { 18 | .container { 19 | width: 2050px; 20 | } 21 | 22 | .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12 { 23 | float: left; 24 | } 25 | 26 | .col-xl-12 { 27 | width: 100%; 28 | } 29 | 30 | .col-xl-11 { 31 | width: 91.66666667%; 32 | } 33 | 34 | .col-xl-10 { 35 | width: 83.33333333%; 36 | } 37 | 38 | .col-xl-9 { 39 | width: 75%; 40 | } 41 | 42 | .col-xl-8 { 43 | width: 66.66666667%; 44 | } 45 | 46 | .col-xl-7 { 47 | width: 58.33333333%; 48 | } 49 | 50 | .col-xl-6 { 51 | width: 50%; 52 | } 53 | 54 | .col-xl-5 { 55 | width: 41.66666667%; 56 | } 57 | 58 | .col-xl-4 { 59 | width: 33.33333333%; 60 | } 61 | 62 | .col-xl-3 { 63 | width: 25%; 64 | } 65 | 66 | .col-xl-2 { 67 | width: 16.66666667%; 68 | } 69 | 70 | .col-xl-1 { 71 | width: 8.33333333%; 72 | } 73 | 74 | .col-xl-pull-12 { 75 | right: 100%; 76 | } 77 | 78 | .col-xl-pull-11 { 79 | right: 91.66666667%; 80 | } 81 | 82 | .col-xl-pull-10 { 83 | right: 83.33333333%; 84 | } 85 | 86 | .col-xl-pull-9 { 87 | right: 75%; 88 | } 89 | 90 | .col-xl-pull-8 { 91 | right: 66.66666667%; 92 | } 93 | 94 | .col-xl-pull-7 { 95 | right: 58.33333333%; 96 | } 97 | 98 | .col-xl-pull-6 { 99 | right: 50%; 100 | } 101 | 102 | .col-xl-pull-5 { 103 | right: 41.66666667%; 104 | } 105 | 106 | .col-xl-pull-4 { 107 | right: 33.33333333%; 108 | } 109 | 110 | .col-xl-pull-3 { 111 | right: 25%; 112 | } 113 | 114 | .col-xl-pull-2 { 115 | right: 16.66666667%; 116 | } 117 | 118 | .col-xl-pull-1 { 119 | right: 8.33333333%; 120 | } 121 | 122 | .col-xl-pull-0 { 123 | right: auto; 124 | } 125 | 126 | .col-xl-push-12 { 127 | left: 100%; 128 | } 129 | 130 | .col-xl-push-11 { 131 | left: 91.66666667%; 132 | } 133 | 134 | .col-xl-push-10 { 135 | left: 83.33333333%; 136 | } 137 | 138 | .col-xl-push-9 { 139 | left: 75%; 140 | } 141 | 142 | .col-xl-push-8 { 143 | left: 66.66666667%; 144 | } 145 | 146 | .col-xl-push-7 { 147 | left: 58.33333333%; 148 | } 149 | 150 | .col-xl-push-6 { 151 | left: 50%; 152 | } 153 | 154 | .col-xl-push-5 { 155 | left: 41.66666667%; 156 | } 157 | 158 | .col-xl-push-4 { 159 | left: 33.33333333%; 160 | } 161 | 162 | .col-xl-push-3 { 163 | left: 25%; 164 | } 165 | 166 | .col-xl-push-2 { 167 | left: 16.66666667%; 168 | } 169 | 170 | .col-xl-push-1 { 171 | left: 8.33333333%; 172 | } 173 | 174 | .col-xl-push-0 { 175 | left: auto; 176 | } 177 | 178 | .col-xl-offset-12 { 179 | margin-left: 100%; 180 | } 181 | 182 | .col-xl-offset-11 { 183 | margin-left: 91.66666667%; 184 | } 185 | 186 | .col-xl-offset-10 { 187 | margin-left: 83.33333333%; 188 | } 189 | 190 | .col-xl-offset-9 { 191 | margin-left: 75%; 192 | } 193 | 194 | .col-xl-offset-8 { 195 | margin-left: 66.66666667%; 196 | } 197 | 198 | .col-xl-offset-7 { 199 | margin-left: 58.33333333%; 200 | } 201 | 202 | .col-xl-offset-6 { 203 | margin-left: 50%; 204 | } 205 | 206 | .col-xl-offset-5 { 207 | margin-left: 41.66666667%; 208 | } 209 | 210 | .col-xl-offset-4 { 211 | margin-left: 33.33333333%; 212 | } 213 | 214 | .col-xl-offset-3 { 215 | margin-left: 25%; 216 | } 217 | 218 | .col-xl-offset-2 { 219 | margin-left: 16.66666667%; 220 | } 221 | 222 | .col-xl-offset-1 { 223 | margin-left: 8.33333333%; 224 | } 225 | 226 | .col-xl-offset-0 { 227 | margin-left: 0; 228 | } 229 | 230 | .visible-xl { 231 | display: block !important; 232 | } 233 | 234 | table.visible-xl { 235 | display: table; 236 | } 237 | 238 | tr.visible-xl { 239 | display: table-row !important; 240 | } 241 | 242 | th.visible-xl, td.visible-xl { 243 | display: table-cell !important; 244 | } 245 | 246 | .visible-xl-block { 247 | display: block !important; 248 | } 249 | 250 | .visible-xl-inline { 251 | display: inline !important; 252 | } 253 | 254 | .visible-xl-inline-block { 255 | display: inline-block !important; 256 | } 257 | 258 | .hidden-xl { 259 | display: none !important; 260 | } 261 | } 262 | -------------------------------------------------------------------------------- /munkido/system_settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | import socket 3 | import logging 4 | from django.conf import global_settings 5 | 6 | #PROJECT_DIR = os.path.dirname(os.path.abspath(__file__)) 7 | PROJECT_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__))) 8 | DEBUG = True 9 | TEMPLATE_DEBUG = DEBUG 10 | ADMINS = ( 11 | # ('Your Name', 'your_email@example.com'), 12 | ) 13 | MANAGERS = ADMINS 14 | 15 | # APPNAME is user-visable web app name 16 | APPNAME = 'Munki-Do' 17 | # MUNKI_REPO_DIR holds the local filesystem path to the Munki repo 18 | MUNKI_REPO_DIR = '/munki_repo' 19 | ICONS_DIR = 'icons' 20 | PKGS_DIR = 'pkgs' 21 | 22 | # The following is used for the download links for pkgs. 23 | # It assumes that the full munki_repo is accessable at /munki_repo 24 | MUNKI_PKG_ROOT = os.path.join(MUNKI_REPO_DIR, PKGS_DIR) 25 | 26 | # path to makecatalogs - required for packages section 27 | DEFAULT_MAKECATALOGS = "/usr/local/munki/makecatalogs" 28 | 29 | # if true all software packages are shown in autocompletion not only the one in included catalogs 30 | ALL_ITEMS = True 31 | 32 | # needed for productive mode 33 | ALLOWED_HOSTS = ['*'] 34 | 35 | TOKEN_TIMEOUT_DAYS = 1 36 | 37 | ANONYMOUS_USER_ID = -1 38 | 39 | # Local time zone for this installation. Choices can be found here: 40 | # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name 41 | # although not all choices may be available on all operating systems. 42 | # On Unix systems, a value of None will cause Django to use the same 43 | # timezone as the operating system. 44 | # If running in a Windows environment this must be set to the same as your 45 | # system time zone. 46 | TIME_ZONE = 'America/New_York' 47 | 48 | # Language code for this installation. All choices can be found here: 49 | # http://www.i18nguy.com/unicode/language-identifiers.html 50 | LANGUAGE_CODE = 'en-US' 51 | 52 | # ----------------- 53 | 54 | SITE_ID = 1 55 | 56 | # If you set this to False, Django will make some optimizations so as not 57 | # to load the internationalization machinery. 58 | USE_I18N = True 59 | 60 | # If you set this to False, Django will not format dates, numbers and 61 | # calendars according to the current locale 62 | USE_L10N = True 63 | 64 | MEDIA_ROOT = os.path.join(MUNKI_REPO_DIR, ICONS_DIR) 65 | 66 | MEDIA_URL = '/media/' 67 | 68 | STATIC_ROOT = os.path.join(PROJECT_DIR, 'static') 69 | 70 | STATIC_URL = '/static/' 71 | 72 | # Additional locations of static files 73 | STATICFILES_DIRS = ( 74 | os.path.join(PROJECT_DIR, 'site_static'), 75 | ) 76 | 77 | STATICFILES_FINDERS = ( 78 | 'django.contrib.staticfiles.finders.FileSystemFinder', 79 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 80 | ) 81 | 82 | # Make this unique, and don't share it with anybody. 83 | SECRET_KEY = 'x@hgx4r!1rm@c4lax96tx88*d1v+m$&)w1ur4-xvcqj(8as_$q' 84 | 85 | TEST_RUNNER = 'django.test.runner.DiscoverRunner' 86 | 87 | TEMPLATE_LOADERS = ( 88 | 'django.template.loaders.filesystem.Loader', 89 | 'django.template.loaders.app_directories.Loader', 90 | ) 91 | 92 | TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + ( 93 | "munkido.processor.index", 94 | "django.core.context_processors.request", 95 | ) 96 | 97 | MIDDLEWARE_CLASSES = ( 98 | 'django.middleware.common.CommonMiddleware', 99 | 'django.contrib.sessions.middleware.SessionMiddleware', 100 | 'django.middleware.csrf.CsrfViewMiddleware', 101 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 102 | 'django.contrib.messages.middleware.MessageMiddleware', 103 | ) 104 | 105 | LOGIN_URL='/login/' 106 | 107 | ROOT_URLCONF = 'munkido.urls' 108 | 109 | TEMPLATE_DIRS = ( 110 | os.path.join(PROJECT_DIR, 'templates'), 111 | ) 112 | 113 | INSTALLED_APPS = ( 114 | 'django.contrib.auth', 115 | 'django.contrib.contenttypes', 116 | 'django.contrib.sessions', 117 | 'django.contrib.sites', 118 | 'django.contrib.messages', 119 | 'django.contrib.staticfiles', 120 | 'django.contrib.admin', 121 | 'munkido', 122 | 'tokenapi', 123 | 'catalogs', 124 | 'manifests', 125 | 'pkgs', 126 | ) 127 | 128 | LOGGING = { 129 | 'version': 1, 130 | 'disable_existing_loggers': False, 131 | 'filters': { 132 | 'require_debug_false': { 133 | '()': 'django.utils.log.RequireDebugFalse' 134 | } 135 | }, 136 | 'handlers': { 137 | 'file': { 138 | 'level': 'ERROR', 139 | 'class': 'logging.FileHandler', 140 | 'formatter': 'verbose', 141 | 'filename': '/var/log/django/error.log', 142 | }, 143 | 'file': { 144 | 'level': 'DEBUG', 145 | 'class': 'logging.FileHandler', 146 | 'formatter': 'verbose', 147 | 'filename': '/var/log/django/debug.log', 148 | }, 149 | 'file': { 150 | 'level': 'INFO', 151 | 'class': 'logging.FileHandler', 152 | 'formatter': 'verbose', 153 | 'filename': '/var/log/django/info.log', 154 | }, 155 | }, 156 | 'formatters': { 157 | 'verbose': { 158 | 'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s' 159 | }, 160 | 'simple': { 161 | 'format': 162 | '%(levelname)s %(message)s' 163 | }, 164 | }, 165 | 'loggers': { 166 | 'django': { 167 | 'handlers':['file'], 168 | 'propagate': True, 169 | 'level':'DEBUG', 170 | }, 171 | 'manifests.models': { 172 | 'handlers': ['file'], 173 | 'level': 'INFO', 174 | 'propagate': True, 175 | }, 176 | 'pkgs.models': { 177 | 'handlers': ['file'], 178 | 'level': 'INFO', 179 | 'propagate': True, 180 | }, 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /munkido/site_static/css/plugins/dataTables.bootstrap.css: -------------------------------------------------------------------------------- 1 | div.dataTables_length label { 2 | float: left; 3 | text-align: left; 4 | font-weight: normal; 5 | } 6 | 7 | div.dataTables_length select { 8 | width: 75px; 9 | } 10 | 11 | div.dataTables_filter label { 12 | float: right; 13 | font-weight: normal; 14 | } 15 | 16 | div.dataTables_filter input { 17 | width: 16em; 18 | } 19 | 20 | div.dataTables_info { 21 | padding-top: 8px; 22 | } 23 | 24 | div.dataTables_paginate { 25 | float: right; 26 | margin: 0; 27 | } 28 | 29 | div.dataTables_paginate ul.pagination { 30 | margin: 2px 0; 31 | white-space: nowrap; 32 | } 33 | 34 | table.dataTable, 35 | table.dataTable td, 36 | table.dataTable th { 37 | -webkit-box-sizing: content-box; 38 | -moz-box-sizing: content-box; 39 | box-sizing: content-box; 40 | } 41 | 42 | table.dataTable { 43 | clear: both; 44 | margin-top: 0px !important; 45 | margin-bottom: 6px !important; 46 | max-width: none !important; 47 | } 48 | 49 | table.dataTable thead .sorting, 50 | table.dataTable thead .sorting_asc, 51 | table.dataTable thead .sorting_desc, 52 | table.dataTable thead .sorting_asc_disabled, 53 | table.dataTable thead .sorting_desc_disabled { 54 | cursor: pointer; 55 | } 56 | 57 | table.dataTable thead .sorting { 58 | background: url('../images/sort_both.png') no-repeat center right; 59 | } 60 | 61 | table.dataTable thead .sorting_asc { 62 | background: url('../images/sort_asc.png') no-repeat center right; 63 | } 64 | 65 | table.dataTable thead .sorting_desc { 66 | background: url('../images/sort_desc.png') no-repeat center right; 67 | } 68 | 69 | table.dataTable thead .sorting_asc_disabled { 70 | background: url('../images/sort_asc_disabled.png') no-repeat center right; 71 | } 72 | 73 | table.dataTable thead .sorting_desc_disabled { 74 | background: url('../images/sort_desc_disabled.png') no-repeat center right; 75 | } 76 | 77 | table.dataTable th:active { 78 | outline: none; 79 | } 80 | 81 | /* Scrolling */ 82 | 83 | div.dataTables_scrollHead table { 84 | margin-bottom: 0 !important; 85 | border-bottom-left-radius: 0; 86 | border-bottom-right-radius: 0; 87 | } 88 | 89 | div.dataTables_scrollHead table thead tr:last-child th:first-child, 90 | div.dataTables_scrollHead table thead tr:last-child td:first-child { 91 | border-bottom-left-radius: 0 !important; 92 | border-bottom-right-radius: 0 !important; 93 | } 94 | 95 | div.dataTables_scrollBody table { 96 | margin-top: 0 !important; 97 | margin-bottom: 0 !important; 98 | border-top: none; 99 | } 100 | 101 | div.dataTables_scrollBody tbody tr:first-child th, 102 | div.dataTables_scrollBody tbody tr:first-child td { 103 | border-top: none; 104 | } 105 | 106 | div.dataTables_scrollFoot table { 107 | margin-top: 0 !important; 108 | border-top: none; 109 | } 110 | 111 | /* 112 | * TableTools styles 113 | */ 114 | 115 | .table-striped tbody tr.active:nth-child(odd) td, 116 | .table-striped tbody tr.active:nth-child(odd) th { 117 | background-color: #017ebc; 118 | } 119 | 120 | table.DTTT_selectable tbody tr { 121 | cursor: pointer; 122 | } 123 | 124 | div.DTTT .btn { 125 | font-size: 12px; 126 | color: #333 !important; 127 | } 128 | 129 | div.DTTT .btn:hover { 130 | text-decoration: none !important; 131 | } 132 | 133 | ul.DTTT_dropdown.dropdown-menu { 134 | z-index: 2003; 135 | } 136 | 137 | ul.DTTT_dropdown.dropdown-menu a { 138 | color: #333 !important; /* needed only when demo_page.css is included */ 139 | } 140 | 141 | ul.DTTT_dropdown.dropdown-menu li { 142 | position: relative; 143 | } 144 | 145 | ul.DTTT_dropdown.dropdown-menu li:hover a { 146 | color: white !important; 147 | background-color: #0088cc; 148 | } 149 | 150 | div.DTTT_collection_background { 151 | z-index: 2002; 152 | } 153 | 154 | /* TableTools information display */ 155 | 156 | div.DTTT_print_info.modal { 157 | height: 150px; 158 | margin-top: -75px; 159 | text-align: center; 160 | } 161 | 162 | div.DTTT_print_info h6 { 163 | margin: 1em; 164 | font-size: 28px; 165 | font-weight: normal; 166 | line-height: 28px; 167 | } 168 | 169 | div.DTTT_print_info p { 170 | font-size: 14px; 171 | line-height: 20px; 172 | } 173 | 174 | /* 175 | * FixedColumns styles 176 | */ 177 | 178 | div.DTFC_LeftHeadWrapper table, 179 | div.DTFC_LeftFootWrapper table, 180 | div.DTFC_RightHeadWrapper table, 181 | div.DTFC_RightFootWrapper table, 182 | table.DTFC_Cloned tr.even { 183 | background-color: white; 184 | } 185 | 186 | div.DTFC_RightHeadWrapper table, 187 | div.DTFC_LeftHeadWrapper table { 188 | margin-bottom: 0 !important; 189 | border-top-right-radius: 0 !important; 190 | border-bottom-left-radius: 0 !important; 191 | border-bottom-right-radius: 0 !important; 192 | } 193 | 194 | div.DTFC_RightHeadWrapper table thead tr:last-child th:first-child, 195 | div.DTFC_RightHeadWrapper table thead tr:last-child td:first-child, 196 | div.DTFC_LeftHeadWrapper table thead tr:last-child th:first-child, 197 | div.DTFC_LeftHeadWrapper table thead tr:last-child td:first-child { 198 | border-bottom-left-radius: 0 !important; 199 | border-bottom-right-radius: 0 !important; 200 | } 201 | 202 | div.DTFC_RightBodyWrapper table, 203 | div.DTFC_LeftBodyWrapper table { 204 | margin-bottom: 0 !important; 205 | border-top: none; 206 | } 207 | 208 | div.DTFC_RightBodyWrapper tbody tr:first-child th, 209 | div.DTFC_RightBodyWrapper tbody tr:first-child td, 210 | div.DTFC_LeftBodyWrapper tbody tr:first-child th, 211 | div.DTFC_LeftBodyWrapper tbody tr:first-child td { 212 | border-top: none; 213 | } 214 | 215 | div.DTFC_RightFootWrapper table, 216 | div.DTFC_LeftFootWrapper table { 217 | border-top: none; 218 | } -------------------------------------------------------------------------------- /munkido/site_static/css/sb-admin-2.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Start Bootstrap - SB Admin Bootstrap Admin Template (http://startbootstrap.com) 3 | * Code licensed under the Apache License v2.0. 4 | * For details, see http://www.apache.org/licenses/LICENSE-2.0. 5 | */ 6 | 7 | /* Global Styles */ 8 | 9 | body { 10 | margin-top: 100px; 11 | background-color: #f8f8f8; 12 | word-wrap: break-word; 13 | } 14 | 15 | @media(min-width:768px) { 16 | body { 17 | margin-top: 50px; 18 | } 19 | } 20 | 21 | .dataTables_filter { 22 | display: none; 23 | } 24 | 25 | /* -------- special kuengst */ 26 | tr { 27 | height: 40px; 28 | } 29 | 30 | .table.table-condensed tr td { 31 | border-bottom: 1px solid #ddd; /* Change the color you want to set */ 32 | } 33 | 34 | .typeahead>li>a { 35 | text-align: left !important; 36 | padding-bottom: 3px !important; 37 | padding-left: 20px !important; 38 | padding-right: 20px !important; 39 | padding-top: 3px !important; 40 | color:#333 !important; 41 | } 42 | 43 | .loading { 44 | -webkit-animation:spin 2s linear infinite; 45 | -moz-animation:spin 2s linear infinite; 46 | animation:spin 2s linear infinite; 47 | } 48 | @-moz-keyframes spin { 100% { 49 | -moz-transform:rotate(360deg); 50 | } 51 | } 52 | @-webkit-keyframes spin { 100% { 53 | -webkit-transform:rotate(360deg); 54 | } 55 | } 56 | @keyframes spin { 100% { 57 | -webkit-transform:rotate(360deg); 58 | transform:rotate(360deg); 59 | } 60 | } 61 | 62 | .loader { 63 | background-color: black; 64 | } 65 | /* ---------------- */ 66 | 67 | @media(max-width:768px) { 68 | tr { 69 | height: 50px; 70 | font-size: 16px; 71 | } 72 | } 73 | 74 | #wrapper { 75 | padding-left: 0; 76 | } 77 | 78 | #page-wrapper { 79 | width: 100%; 80 | padding: 0; 81 | background-color: #fff; 82 | border-left: 1px solid #e7e7e7; 83 | border-top: 1px solid #e7e7e7; 84 | border-bottom: 1px solid #e7e7e7; 85 | } 86 | 87 | .container-fluid { 88 | padding-top: 10px; 89 | } 90 | 91 | .huge { 92 | font-size: 50px; 93 | line-height: normal; 94 | } 95 | 96 | @media(min-width:768px) { 97 | #wrapper { 98 | padding-left: 200px; 99 | } 100 | 101 | #page-wrapper { 102 | padding: 10px; 103 | box-shadow: 0 0 6px #ccc; 104 | z-index:1030; 105 | position:relative; 106 | } 107 | } 108 | 109 | .side-nav ul li a.active { 110 | background-color: #eee; 111 | } 112 | 113 | /* Top Navigation */ 114 | 115 | .top-nav { 116 | padding: 0 15px; 117 | } 118 | 119 | .top-nav>li { 120 | display: inline-block; 121 | float: left; 122 | } 123 | 124 | .top-nav>li>a { 125 | padding-top: 15px; 126 | padding-bottom: 15px; 127 | line-height: 20px; 128 | color: #999; 129 | } 130 | 131 | .top-nav>li>a:hover, 132 | .top-nav>li>a:focus, 133 | .top-nav>.open>a, 134 | .top-nav>.open>a:hover, 135 | .top-nav>.open>a:focus { 136 | color: #000; 137 | background-color: #e7e7e7; 138 | } 139 | 140 | .top-nav>.open>.dropdown-menu { 141 | float: left; 142 | position: absolute; 143 | margin-top: 0; 144 | border: 1px solid rgba(0,0,0,.15); 145 | border-top-left-radius: 0; 146 | border-top-right-radius: 0; 147 | background-color: #fff; 148 | -webkit-box-shadow: 0 6px 12px rgba(0,0,0,.175); 149 | box-shadow: 0 6px 12px rgba(0,0,0,.175); 150 | } 151 | 152 | .top-nav>.open>.dropdown-menu>li>a { 153 | white-space: normal; 154 | } 155 | 156 | ul.message-dropdown { 157 | padding: 0; 158 | max-height: 250px; 159 | overflow-x: hidden; 160 | overflow-y: auto; 161 | } 162 | 163 | li.message-preview { 164 | width: 275px; 165 | border-bottom: 1px solid rgba(0,0,0,.15); 166 | } 167 | 168 | li.message-preview>a { 169 | padding-top: 15px; 170 | padding-bottom: 15px; 171 | } 172 | 173 | li.message-footer { 174 | margin: 5px 0; 175 | } 176 | 177 | ul.alert-dropdown { 178 | width: 200px; 179 | } 180 | 181 | /* Side Navigation */ 182 | 183 | @media(min-width:768px) { 184 | .side-nav { 185 | position: fixed; 186 | top: 51px; 187 | left: 200px; 188 | width: 200px; 189 | margin-left: -200px; 190 | border-radius: 0; 191 | overflow-y: auto; 192 | background-color: #f8f8f8; 193 | border-bottom: 1px solid #e7e7e7; 194 | } 195 | 196 | .side-nav>li>a { 197 | width: 200px; 198 | border-top: 1px solid #e7e7e7; 199 | } 200 | 201 | .side-nav li a:hover, 202 | .side-nav li a:focus { 203 | outline: none; 204 | background-color: #e7e7e7 !important; 205 | } 206 | } 207 | 208 | .side-nav>li>ul { 209 | padding: 0; 210 | } 211 | 212 | .side-nav>li>ul>li>a { 213 | display: block; 214 | padding: 10px 15px 10px 25px; 215 | text-decoration: none; 216 | color: #999; 217 | } 218 | 219 | .side-nav>li>ul>li>a:hover { 220 | color: #fff; 221 | } 222 | 223 | /* Flot Chart Containers */ 224 | 225 | .flot-chart { 226 | display: block; 227 | height: 400px; 228 | } 229 | 230 | .flot-chart-content { 231 | width: 100%; 232 | height: 100%; 233 | } 234 | 235 | /* Custom Colored Panels */ 236 | 237 | .huge { 238 | font-size: 40px; 239 | } 240 | 241 | .panel-green { 242 | border-color: #5cb85c; 243 | } 244 | 245 | .panel-green .panel-heading { 246 | border-color: #5cb85c; 247 | color: #fff; 248 | background-color: #5cb85c; 249 | } 250 | 251 | .panel-green a { 252 | color: #5cb85c; 253 | } 254 | 255 | .panel-green a:hover { 256 | color: #3d8b3d; 257 | } 258 | 259 | .panel-red { 260 | border-color: #d9534f; 261 | } 262 | 263 | .panel-red .panel-heading { 264 | border-color: #d9534f; 265 | color: #fff; 266 | background-color: #d9534f; 267 | } 268 | 269 | .panel-red a { 270 | color: #d9534f; 271 | } 272 | 273 | .panel-red a:hover { 274 | color: #b52b27; 275 | } 276 | 277 | .panel-yellow { 278 | border-color: #f0ad4e; 279 | } 280 | 281 | .panel-yellow .panel-heading { 282 | border-color: #f0ad4e; 283 | color: #fff; 284 | background-color: #f0ad4e; 285 | } 286 | 287 | .panel-yellow a { 288 | color: #f0ad4e; 289 | } 290 | 291 | .panel-yellow a:hover { 292 | color: #df8a13; 293 | } 294 | -------------------------------------------------------------------------------- /manifests/templates/manifests/detail.html: -------------------------------------------------------------------------------- 1 | {% if manifest %} 2 |

3 | {{ manifest_name }} 4 | {% if manifest_restriction %} (restricted) {% endif %} 5 |
6 | {% if perms.manifests.delete_manifests and manifest_restriction_is_editable %} 7 | 8 | {% endif %} 9 | {% if perms.manifests.change_manifests and manifest_restriction_is_editable %} 10 | 11 | {% endif %} 12 |
13 |

14 |
15 | {% if user %} 16 | 30 | {% endif %} 31 | 32 | {% if restriction_key %} 33 |
34 | 35 |
    36 | {% for item in manifest_restriction %} 37 |
  • 40 | {% else %} 41 | list-group-item-danger'> 42 | {% endif %} 43 |
    {{ item }}
    44 |
  • 45 | {% endfor %} 46 |
47 |
48 | {% endif %} 49 | 50 |
51 | 52 | 70 |
71 | 72 | {% if manifest.conditional_items %} 73 |
74 | 75 | viewing/editing conditional_items not currently supported 76 |

77 |

78 | {% endif %} 79 | 80 |
81 | 82 |
    83 | {% for i_manifest in manifest.included_manifests %} 84 |
  • 87 |
    {{ i_manifest }}
    88 | {% else %} 89 | list-group-item-info'> 90 | 91 |
    {{ i_manifest }}
    92 |
    93 | {% endif %} 94 |
  • 95 | {% endfor %} 96 |
97 |
98 | 99 |
100 | 101 |
    102 | {% for item in manifest.managed_installs|dictsort:"lstrip" %} 103 |
  • 107 |
    {{ item }}
    108 |
  • 109 | {% endfor %} 110 |
111 |
112 | 113 |
114 | 115 |
    116 | {% for item in manifest.managed_uninstalls|dictsort:"lstrip" %} 117 |
  • 121 |
    {{ item }}
    122 |
  • 123 | {% endfor %} 124 |
125 |
126 | 127 | {% if MANAGED_UPDATES_ENABLED %} 128 |
129 | 130 |
    131 | {% for item in manifest.managed_updates|dictsort:"lstrip" %} 132 |
  • 136 |
    {{ item }}
    137 |
  • 138 | {% endfor %} 139 |
140 |
141 | {% endif %} 142 | 143 |
144 | 145 |
    146 | {% for item in manifest.optional_installs|dictsort:"lstrip" %} 147 |
  • 151 |
    {{ item }}
    152 |
  • 153 | {% endfor %} 154 |
155 |
156 |
157 |
158 | 159 | {% elif git_branching_enabled %} 160 |
Git branching enabled. Please refresh your view or click below:
161 | 164 | 165 | {% else %} 166 |
Manifest is empty
167 | {% endif %} 168 | -------------------------------------------------------------------------------- /munkido/site_static/less/sb-admin-2.less: -------------------------------------------------------------------------------- 1 | @import "variables.less"; 2 | @import "mixins.less"; 3 | 4 | // Global Styles 5 | 6 | body { 7 | background-color: @gray-lightest; 8 | } 9 | 10 | // Wrappers 11 | 12 | #wrapper { 13 | width: 100%; 14 | } 15 | 16 | #page-wrapper { 17 | padding: 0 15px; 18 | min-height: 568px; 19 | background-color: white; 20 | } 21 | 22 | @media(min-width:768px) { 23 | #page-wrapper { 24 | position: inherit; 25 | margin: 0 0 0 250px; 26 | padding: 0 30px; 27 | border-left: 1px solid darken(@gray-lightest, 6.5%); 28 | } 29 | } 30 | 31 | // Navigation 32 | 33 | // --Topbar 34 | 35 | .navbar-top-links li { 36 | display: inline-block; 37 | } 38 | 39 | .navbar-top-links li:last-child { 40 | margin-right: 15px; 41 | } 42 | 43 | .navbar-top-links li a { 44 | padding: 15px; 45 | min-height: 50px; 46 | } 47 | 48 | .navbar-top-links .dropdown-menu li { 49 | display: block; 50 | } 51 | 52 | .navbar-top-links .dropdown-menu li:last-child { 53 | margin-right: 0; 54 | } 55 | 56 | .navbar-top-links .dropdown-menu li a { 57 | padding: 3px 20px; 58 | min-height: 0; 59 | } 60 | 61 | .navbar-top-links .dropdown-menu li a div { 62 | white-space: normal; 63 | } 64 | 65 | .navbar-top-links .dropdown-messages, 66 | .navbar-top-links .dropdown-tasks, 67 | .navbar-top-links .dropdown-alerts { 68 | width: 310px; 69 | min-width: 0; 70 | } 71 | 72 | .navbar-top-links .dropdown-messages { 73 | margin-left: 5px; 74 | } 75 | 76 | .navbar-top-links .dropdown-tasks { 77 | margin-left: -59px; 78 | } 79 | 80 | .navbar-top-links .dropdown-alerts { 81 | margin-left: -123px; 82 | } 83 | 84 | .navbar-top-links .dropdown-user { 85 | right: 0; 86 | left: auto; 87 | } 88 | 89 | // --Sidebar 90 | 91 | .sidebar { 92 | .sidebar-nav.navbar-collapse { 93 | padding-left: 0; 94 | padding-right: 0; 95 | } 96 | } 97 | 98 | .sidebar .sidebar-search { 99 | padding: 15px; 100 | } 101 | 102 | .sidebar ul li { 103 | border-bottom: 1px solid darken(@gray-lightest, 6.5%); 104 | a { 105 | &.active { 106 | background-color: @gray-lighter; 107 | } 108 | } 109 | } 110 | 111 | .sidebar .arrow { 112 | float: right; 113 | } 114 | 115 | .sidebar .fa.arrow:before { 116 | content: "\f104"; 117 | } 118 | 119 | .sidebar .active > a > .fa.arrow:before { 120 | content: "\f107"; 121 | } 122 | 123 | .sidebar .nav-second-level li, 124 | .sidebar .nav-third-level li { 125 | border-bottom: none !important; 126 | } 127 | 128 | .sidebar .nav-second-level li a { 129 | padding-left: 37px; 130 | } 131 | 132 | .sidebar .nav-third-level li a { 133 | padding-left: 52px; 134 | } 135 | 136 | @media(min-width:768px) { 137 | .sidebar { 138 | z-index: 1; 139 | position: absolute; 140 | width: 250px; 141 | margin-top: 51px; 142 | } 143 | 144 | .navbar-top-links .dropdown-messages, 145 | .navbar-top-links .dropdown-tasks, 146 | .navbar-top-links .dropdown-alerts { 147 | margin-left: auto; 148 | } 149 | } 150 | 151 | // Buttons 152 | 153 | .btn-outline { 154 | color: inherit; 155 | background-color: transparent; 156 | transition: all .5s; 157 | } 158 | 159 | .btn-primary.btn-outline { 160 | color: @brand-primary; 161 | } 162 | 163 | .btn-success.btn-outline { 164 | color: @brand-success; 165 | } 166 | 167 | .btn-info.btn-outline { 168 | color: @brand-info; 169 | } 170 | 171 | .btn-warning.btn-outline { 172 | color: @brand-warning; 173 | } 174 | 175 | .btn-danger.btn-outline { 176 | color: @brand-danger; 177 | } 178 | 179 | .btn-primary.btn-outline:hover, 180 | .btn-success.btn-outline:hover, 181 | .btn-info.btn-outline:hover, 182 | .btn-warning.btn-outline:hover, 183 | .btn-danger.btn-outline:hover { 184 | color: white; 185 | } 186 | 187 | // Chat Widget 188 | 189 | .chat { 190 | margin: 0; 191 | padding: 0; 192 | list-style: none; 193 | } 194 | 195 | .chat li { 196 | margin-bottom: 10px; 197 | padding-bottom: 5px; 198 | border-bottom: 1px dotted @gray-light; 199 | } 200 | 201 | .chat li.left .chat-body { 202 | margin-left: 60px; 203 | } 204 | 205 | .chat li.right .chat-body { 206 | margin-right: 60px; 207 | } 208 | 209 | .chat li .chat-body p { 210 | margin: 0; 211 | } 212 | 213 | .panel .slidedown .glyphicon, 214 | .chat .glyphicon { 215 | margin-right: 5px; 216 | } 217 | 218 | .chat-panel .panel-body { 219 | height: 350px; 220 | overflow-y: scroll; 221 | } 222 | 223 | // Login Page 224 | 225 | .login-panel { 226 | margin-top: 25%; 227 | } 228 | 229 | // Flot Charts Containers 230 | 231 | .flot-chart { 232 | display: block; 233 | height: 400px; 234 | } 235 | 236 | .flot-chart-content { 237 | width: 100%; 238 | height: 100%; 239 | } 240 | 241 | // DataTables Overrides 242 | 243 | table.dataTable thead .sorting, 244 | table.dataTable thead .sorting_asc, 245 | table.dataTable thead .sorting_desc, 246 | table.dataTable thead .sorting_asc_disabled, 247 | table.dataTable thead .sorting_desc_disabled { 248 | background: transparent; 249 | } 250 | 251 | table.dataTable thead .sorting_asc:after { 252 | content: "\f0de"; 253 | float: right; 254 | font-family: fontawesome; 255 | } 256 | 257 | table.dataTable thead .sorting_desc:after { 258 | content: "\f0dd"; 259 | float: right; 260 | font-family: fontawesome; 261 | } 262 | 263 | table.dataTable thead .sorting:after { 264 | content: "\f0dc"; 265 | float: right; 266 | font-family: fontawesome; 267 | color: rgba(50,50,50,.5); 268 | } 269 | 270 | // Circle Buttons 271 | 272 | .btn-circle { 273 | width: 30px; 274 | height: 30px; 275 | padding: 6px 0; 276 | border-radius: 15px; 277 | text-align: center; 278 | font-size: 12px; 279 | line-height: 1.428571429; 280 | } 281 | 282 | .btn-circle.btn-lg { 283 | width: 50px; 284 | height: 50px; 285 | padding: 10px 16px; 286 | border-radius: 25px; 287 | font-size: 18px; 288 | line-height: 1.33; 289 | } 290 | 291 | .btn-circle.btn-xl { 292 | width: 70px; 293 | height: 70px; 294 | padding: 10px 16px; 295 | border-radius: 35px; 296 | font-size: 24px; 297 | line-height: 1.33; 298 | } 299 | 300 | // Grid Demo Elements 301 | 302 | .show-grid [class^="col-"] { 303 | padding-top: 10px; 304 | padding-bottom: 10px; 305 | border: 1px solid #ddd; 306 | background-color: #eee !important; 307 | } 308 | 309 | .show-grid { 310 | margin: 15px 0; 311 | } 312 | 313 | // Custom Colored Panels 314 | 315 | .huge { 316 | font-size: 40px; 317 | } 318 | 319 | .panel-green { 320 | border-color: @brand-success; 321 | .panel-heading { 322 | border-color: @brand-success; 323 | color: white; 324 | background-color: @brand-success; 325 | } 326 | a { 327 | color: @brand-success; 328 | &:hover { 329 | color: darken(@brand-success, 15%); 330 | } 331 | } 332 | } 333 | 334 | .panel-red { 335 | border-color: @brand-danger; 336 | .panel-heading { 337 | border-color: @brand-danger; 338 | color: white; 339 | background-color: @brand-danger; 340 | } 341 | a { 342 | color: @brand-danger; 343 | &:hover { 344 | color: darken(@brand-danger, 15%); 345 | } 346 | } 347 | } 348 | 349 | .panel-yellow { 350 | border-color: @brand-warning; 351 | .panel-heading { 352 | border-color: @brand-warning; 353 | color: white; 354 | background-color: @brand-warning; 355 | } 356 | a { 357 | color: @brand-warning; 358 | &:hover { 359 | color: darken(@brand-warning, 15%); 360 | } 361 | } 362 | } 363 | -------------------------------------------------------------------------------- /munkido/site_static/js/bootbox.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * bootbox.js v4.3.0 3 | * 4 | * http://bootboxjs.com/license.txt 5 | */ 6 | !function(a,b){"use strict";"function"==typeof define&&define.amd?define(["jquery"],b):"object"==typeof exports?module.exports=b(require("jquery")):a.bootbox=b(a.jQuery)}(this,function a(b,c){"use strict";function d(a){var b=q[o.locale];return b?b[a]:q.en[a]}function e(a,c,d){a.stopPropagation(),a.preventDefault();var e=b.isFunction(d)&&d(a)===!1;e||c.modal("hide")}function f(a){var b,c=0;for(b in a)c++;return c}function g(a,c){var d=0;b.each(a,function(a,b){c(a,b,d++)})}function h(a){var c,d;if("object"!=typeof a)throw new Error("Please supply an object of options");if(!a.message)throw new Error("Please specify a message");return a=b.extend({},o,a),a.buttons||(a.buttons={}),a.backdrop=a.backdrop?"static":!1,c=a.buttons,d=f(c),g(c,function(a,e,f){if(b.isFunction(e)&&(e=c[a]={callback:e}),"object"!==b.type(e))throw new Error("button with key "+a+" must be an object");e.label||(e.label=a),e.className||(e.className=2>=d&&f===d-1?"btn-primary":"btn-default")}),a}function i(a,b){var c=a.length,d={};if(1>c||c>2)throw new Error("Invalid argument length");return 2===c||"string"==typeof a[0]?(d[b[0]]=a[0],d[b[1]]=a[1]):d=a[0],d}function j(a,c,d){return b.extend(!0,{},a,i(c,d))}function k(a,b,c,d){var e={className:"bootbox-"+a,buttons:l.apply(null,b)};return m(j(e,d,c),b)}function l(){for(var a={},b=0,c=arguments.length;c>b;b++){var e=arguments[b],f=e.toLowerCase(),g=e.toUpperCase();a[f]={label:d(g)}}return a}function m(a,b){var d={};return g(b,function(a,b){d[b]=!0}),g(a.buttons,function(a){if(d[a]===c)throw new Error("button key "+a+" is not allowed (options are "+b.join("\n")+")")}),a}var n={dialog:"",header:"",footer:"",closeButton:"",form:"
",inputs:{text:"",textarea:"",email:"",select:"",checkbox:"
",date:"",time:"",number:"",password:""}},o={locale:"en",backdrop:!0,animate:!0,className:null,closeButton:!0,show:!0,container:"body"},p={};p.alert=function(){var a;if(a=k("alert",["ok"],["message","callback"],arguments),a.callback&&!b.isFunction(a.callback))throw new Error("alert requires callback property to be a function when provided");return a.buttons.ok.callback=a.onEscape=function(){return b.isFunction(a.callback)?a.callback():!0},p.dialog(a)},p.confirm=function(){var a;if(a=k("confirm",["cancel","confirm"],["message","callback"],arguments),a.buttons.cancel.callback=a.onEscape=function(){return a.callback(!1)},a.buttons.confirm.callback=function(){return a.callback(!0)},!b.isFunction(a.callback))throw new Error("confirm requires a callback");return p.dialog(a)},p.prompt=function(){var a,d,e,f,h,i,k;if(f=b(n.form),d={className:"bootbox-prompt",buttons:l("cancel","confirm"),value:"",inputType:"text"},a=m(j(d,arguments,["title","callback"]),["cancel","confirm"]),i=a.show===c?!0:a.show,a.message=f,a.buttons.cancel.callback=a.onEscape=function(){return a.callback(null)},a.buttons.confirm.callback=function(){var c;switch(a.inputType){case"text":case"textarea":case"email":case"select":case"date":case"time":case"number":case"password":c=h.val();break;case"checkbox":var d=h.find("input:checked");c=[],g(d,function(a,d){c.push(b(d).val())})}return a.callback(c)},a.show=!1,!a.title)throw new Error("prompt requires a title");if(!b.isFunction(a.callback))throw new Error("prompt requires a callback");if(!n.inputs[a.inputType])throw new Error("invalid prompt type");switch(h=b(n.inputs[a.inputType]),a.inputType){case"text":case"textarea":case"email":case"date":case"time":case"number":case"password":h.val(a.value);break;case"select":var o={};if(k=a.inputOptions||[],!k.length)throw new Error("prompt with select requires options");g(k,function(a,d){var e=h;if(d.value===c||d.text===c)throw new Error("given options in wrong format");d.group&&(o[d.group]||(o[d.group]=b("").attr("label",d.group)),e=o[d.group]),e.append("")}),g(o,function(a,b){h.append(b)}),h.val(a.value);break;case"checkbox":var q=b.isArray(a.value)?a.value:[a.value];if(k=a.inputOptions||[],!k.length)throw new Error("prompt with checkbox requires options");if(!k[0].value||!k[0].text)throw new Error("given options in wrong format");h=b("
"),g(k,function(c,d){var e=b(n.inputs[a.inputType]);e.find("input").attr("value",d.value),e.find("label").append(d.text),g(q,function(a,b){b===d.value&&e.find("input").prop("checked",!0)}),h.append(e)})}return a.placeholder&&h.attr("placeholder",a.placeholder),a.pattern&&h.attr("pattern",a.pattern),f.append(h),f.on("submit",function(a){a.preventDefault(),a.stopPropagation(),e.find(".btn-primary").click()}),e=p.dialog(a),e.off("shown.bs.modal"),e.on("shown.bs.modal",function(){h.focus()}),i===!0&&e.modal("show"),e},p.dialog=function(a){a=h(a);var c=b(n.dialog),d=c.find(".modal-dialog"),f=c.find(".modal-body"),i=a.buttons,j="",k={onEscape:a.onEscape};if(g(i,function(a,b){j+="",k[a]=b.callback}),f.find(".bootbox-body").html(a.message),a.animate===!0&&c.addClass("fade"),a.className&&c.addClass(a.className),"large"===a.size&&d.addClass("modal-lg"),"small"===a.size&&d.addClass("modal-sm"),a.title&&f.before(n.header),a.closeButton){var l=b(n.closeButton);a.title?c.find(".modal-header").prepend(l):l.css("margin-top","-10px").prependTo(f)}return a.title&&c.find(".modal-title").html(a.title),j.length&&(f.after(n.footer),c.find(".modal-footer").html(j)),c.on("hidden.bs.modal",function(a){a.target===this&&c.remove()}),c.on("shown.bs.modal",function(){c.find(".btn-primary:first").focus()}),c.on("escape.close.bb",function(a){k.onEscape&&e(a,c,k.onEscape)}),c.on("click",".modal-footer button",function(a){var d=b(this).data("bb-handler");e(a,c,k[d])}),c.on("click",".bootbox-close-button",function(a){e(a,c,k.onEscape)}),c.on("keyup",function(a){27===a.which&&c.trigger("escape.close.bb")}),b(a.container).append(c),c.modal({backdrop:a.backdrop,keyboard:!1,show:!1}),a.show&&c.modal("show"),c},p.setDefaults=function(){var a={};2===arguments.length?a[arguments[0]]=arguments[1]:a=arguments[0],b.extend(o,a)},p.hideAll=function(){return b(".bootbox").modal("hide"),p};var q={br:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Sim"},cs:{OK:"OK",CANCEL:"Zrušit",CONFIRM:"Potvrdit"},da:{OK:"OK",CANCEL:"Annuller",CONFIRM:"Accepter"},de:{OK:"OK",CANCEL:"Abbrechen",CONFIRM:"Akzeptieren"},el:{OK:"Εντάξει",CANCEL:"Ακύρωση",CONFIRM:"Επιβεβαίωση"},en:{OK:"OK",CANCEL:"Cancel",CONFIRM:"OK"},es:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Aceptar"},et:{OK:"OK",CANCEL:"Katkesta",CONFIRM:"OK"},fi:{OK:"OK",CANCEL:"Peruuta",CONFIRM:"OK"},fr:{OK:"OK",CANCEL:"Annuler",CONFIRM:"D'accord"},he:{OK:"אישור",CANCEL:"ביטול",CONFIRM:"אישור"},id:{OK:"OK",CANCEL:"Batal",CONFIRM:"OK"},it:{OK:"OK",CANCEL:"Annulla",CONFIRM:"Conferma"},ja:{OK:"OK",CANCEL:"キャンセル",CONFIRM:"確認"},lt:{OK:"Gerai",CANCEL:"Atšaukti",CONFIRM:"Patvirtinti"},lv:{OK:"Labi",CANCEL:"Atcelt",CONFIRM:"Apstiprināt"},nl:{OK:"OK",CANCEL:"Annuleren",CONFIRM:"Accepteren"},no:{OK:"OK",CANCEL:"Avbryt",CONFIRM:"OK"},pl:{OK:"OK",CANCEL:"Anuluj",CONFIRM:"Potwierdź"},pt:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Confirmar"},ru:{OK:"OK",CANCEL:"Отмена",CONFIRM:"Применить"},sv:{OK:"OK",CANCEL:"Avbryt",CONFIRM:"OK"},tr:{OK:"Tamam",CANCEL:"İptal",CONFIRM:"Onayla"},zh_CN:{OK:"OK",CANCEL:"取消",CONFIRM:"确认"},zh_TW:{OK:"OK",CANCEL:"取消",CONFIRM:"確認"}};return p.init=function(c){return a(c||b)},p}); -------------------------------------------------------------------------------- /munkido/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {% load static %} 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {% block extra_style %}{% endblock %} 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | {% block java_script %}{% endblock %} 47 | 48 | 49 | 50 | 51 | 52 | Munki-Do 53 | 54 | 55 | 59 | 60 | {% block body_tag %} 61 | {% endblock %} 62 |
63 | {% block main_menu %} 64 | 65 | 132 | {% endblock %} 133 | 134 | 135 |
136 |
137 | {% block content %}{% endblock %} 138 |
139 |
140 | 141 |
142 | 147 |
148 | 151 |
152 | 157 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /munkido/settings_template.py: -------------------------------------------------------------------------------- 1 | import os 2 | import socket 3 | import logging 4 | from django.conf import global_settings 5 | 6 | ############################## 7 | # Munki-Do-specific settings # 8 | ############################## 9 | 10 | # APPNAME is user-visable web app name 11 | APPNAME = 'Munki-Do' 12 | # MUNKI_REPO_DIR holds the local filesystem path to the Munki repo 13 | MUNKI_REPO_DIR = '/munki_repo' 14 | ICONS_DIR = 'icons' 15 | PKGS_DIR = 'pkgs' 16 | 17 | ## GIT STUFF ## 18 | # provide the path to the git binary if you want MunkiWeb to add and commit 19 | # manifest edits to a git repo 20 | # if GIT_PATH is undefined or None MunkiWeb will not attempt to do a git add 21 | # or commit 22 | GIT_PATH = '' 23 | #GIT_PATH = '/usr/bin/git' 24 | # If GIT_IGNORE_PKGS is empty, git will attempt to remove packages. 25 | # Otherwise, the packages will be deleted as standard. 26 | GIT_IGNORE_PKGS = 'yes' 27 | # If GIT_BRANCHING is enabled, users create a new branch when making a commit 28 | # (if that branch doesn't already exist) rather than committing to the 29 | # current branch) 30 | #GIT_BRANCHING = 'yes' 31 | GIT_BRANCHING = '' 32 | # If Git branching is available, you should set the default branch here. 33 | # This is the branch which people logging into Munki-Dp will see. 34 | # This may be master, or something else if you have a different workflow. 35 | PRODUCTION_BRANCH = 'master' 36 | ## END OF GIT STUFF ## 37 | 38 | # The following is used for the download links for pkgs. 39 | # It assumes that the full munki_repo is accessable at /munki_repo 40 | MUNKI_PKG_ROOT = os.path.join(MUNKI_REPO_DIR, PKGS_DIR) 41 | 42 | # name of the key in a manifest file that names the user or dept 43 | MANIFEST_USERNAME_KEY = 'user' 44 | # set MANIFEST_USERNAME_IS_EDITABLE to allow edits to the displayed username 45 | MANIFEST_USERNAME_IS_EDITABLE = True 46 | 47 | # path to makecatalogs - required for packages section 48 | #DEFAULT_MAKECATALOGS = "/usr/local/munki/makecatalogs" 49 | DEFAULT_MAKECATALOGS = "/munki-tools/code/client/makecatalogs" 50 | 51 | #if true all software packages are shown in autocompletion not only the one in included catalogs 52 | ALL_ITEMS = True 53 | 54 | # enable Business units 55 | BUSINESS_UNITS_ENABLED = False 56 | 57 | # needed for productive mode 58 | ALLOWED_HOSTS = ['*'] 59 | 60 | TOKEN_TIMEOUT_DAYS = 1 61 | 62 | ANONYMOUS_USER_ID = -1 63 | 64 | # ------------------------- 65 | 66 | USE_LDAP = False 67 | # LDAP authentication support 68 | if USE_LDAP: 69 | import ldap 70 | from django_auth_ldap.config import LDAPSearch, PosixGroupType 71 | 72 | # LDAP settings 73 | AUTH_LDAP_SERVER_URI = "ldap://foo.example.com" 74 | AUTH_LDAP_BIND_DN = "" 75 | AUTH_LDAP_BIND_PASSWORD = "" 76 | AUTH_LDAP_USER_SEARCH = LDAPSearch( 77 | "ou=People,o=ExampleCorp,c=US", 78 | ldap.SCOPE_SUBTREE, "(uid=%(user)s)") 79 | AUTH_LDAP_GROUP_SEARCH = LDAPSearch( 80 | "ou=Groups,o=ExampleCorp,c=US", 81 | ldap.SCOPE_SUBTREE, "(objectClass=posixGroup)") 82 | AUTH_LDAP_GROUP_TYPE = PosixGroupType() 83 | AUTH_LDAP_FIND_GROUP_PERMS = True 84 | AUTH_LDAP_USER_ATTR_MAP = {"first_name": "givenName", 85 | "last_name": "sn", 86 | "email": "mail"} 87 | # Cache group memberships for an hour to minimize LDAP traffic 88 | AUTH_LDAP_CACHE_GROUPS = True 89 | AUTH_LDAP_GROUP_CACHE_TIMEOUT = 3600 90 | 91 | PROJECT_DIR = os.path.dirname(os.path.abspath(__file__)) 92 | DEBUG = True 93 | TEMPLATE_DEBUG = DEBUG 94 | 95 | ADMINS = ( 96 | ('Admin', 'admin@mydomain.com'), 97 | ) 98 | 99 | MANAGERS = ADMINS 100 | 101 | # using sqlite3 102 | DATABASES = { 103 | 'default': { 104 | 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. 105 | 'NAME': '/munki-do-db/munki-do.db', # Path to database file if using sqlite3. 106 | 'USER': '', # Not used with sqlite3. 107 | 'PASSWORD': '', # Not used with sqlite3. 108 | 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. 109 | 'PORT': '', # Set to empty string for default. Not used with sqlite3. 110 | } 111 | } 112 | 113 | # mysql example 114 | #DATABASES = { 115 | # 'default': { 116 | # 'ENGINE': 'django.db.backends.mysql', 117 | # 'NAME': 'munkiweb', 118 | # 'USER': 'munkiwebuser', 119 | # 'PASSWORD': 'munkiwebuserpasswd', 120 | # 'HOST': 'munkiwebdb.example.org', 121 | # 'PORT': '', 122 | # } 123 | #} 124 | 125 | # Local time zone for this installation. Choices can be found here: 126 | # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name 127 | # although not all choices may be available on all operating systems. 128 | # On Unix systems, a value of None will cause Django to use the same 129 | # timezone as the operating system. 130 | # If running in a Windows environment this must be set to the same as your 131 | # system time zone. 132 | TIME_ZONE = 'Europe/Zurich' 133 | 134 | # Language code for this installation. All choices can be found here: 135 | # http://www.i18nguy.com/unicode/language-identifiers.html 136 | LANGUAGE_CODE = 'en-US' 137 | 138 | # ----------------- 139 | 140 | SITE_ID = 1 141 | 142 | # If you set this to False, Django will make some optimizations so as not 143 | # to load the internationalization machinery. 144 | USE_I18N = True 145 | 146 | # If you set this to False, Django will not format dates, numbers and 147 | # calendars according to the current locale 148 | USE_L10N = True 149 | 150 | MEDIA_ROOT = os.path.join(MUNKI_REPO_DIR, ICONS_DIR) 151 | 152 | MEDIA_URL = '/media/' 153 | 154 | STATIC_ROOT = os.path.join(PROJECT_DIR, 'static') 155 | 156 | STATIC_URL = '/static/' 157 | 158 | # Additional locations of static files 159 | STATICFILES_DIRS = ( 160 | os.path.join(PROJECT_DIR, 'site_static'), 161 | ) 162 | 163 | STATICFILES_FINDERS = ( 164 | 'django.contrib.staticfiles.finders.FileSystemFinder', 165 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 166 | ) 167 | 168 | # Make this unique, and don't share it with anybody. 169 | SECRET_KEY = 'x@hgx4r!1rm@c4lax96tx88*d1v+m$&)w1ur4-xvcqj(8as_$q' 170 | 171 | TEST_RUNNER = 'django.test.runner.DiscoverRunner' 172 | 173 | TEMPLATE_LOADERS = ( 174 | 'django.template.loaders.filesystem.Loader', 175 | 'django.template.loaders.app_directories.Loader', 176 | ) 177 | 178 | TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + ( 179 | "munkido.processor.index", 180 | "django.core.context_processors.request", 181 | ) 182 | 183 | MIDDLEWARE_CLASSES = ( 184 | 'django.middleware.common.CommonMiddleware', 185 | 'django.contrib.sessions.middleware.SessionMiddleware', 186 | 'django.middleware.csrf.CsrfViewMiddleware', 187 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 188 | 'django.contrib.messages.middleware.MessageMiddleware', 189 | ) 190 | 191 | if USE_LDAP: 192 | AUTHENTICATION_BACKENDS = ( 193 | 'django_auth_ldap.backend.LDAPBackend', 194 | 'django.contrib.auth.backends.ModelBackend', 195 | 'tokenapi.backends.TokenBackend', 196 | ) 197 | else: 198 | AUTHENTICATION_BACKENDS = ( 199 | 'django.contrib.auth.backends.ModelBackend', 200 | 'tokenapi.backends.TokenBackend', 201 | ) 202 | 203 | LOGIN_URL='/login/' 204 | LOGIN_REDIRECT_URL='/catalogs' 205 | 206 | ROOT_URLCONF = 'munkido.urls' 207 | 208 | TEMPLATE_DIRS = ( 209 | os.path.join(PROJECT_DIR, 'templates'), 210 | ) 211 | 212 | INSTALLED_APPS = ( 213 | 'django.contrib.auth', 214 | 'django.contrib.contenttypes', 215 | 'django.contrib.sessions', 216 | 'django.contrib.sites', 217 | 'django.contrib.messages', 218 | 'django.contrib.staticfiles', 219 | 'django.contrib.admin', 220 | 'munkido', 221 | 'tokenapi', 222 | 'catalogs', 223 | 'manifests', 224 | 'pkgs', 225 | ) 226 | 227 | LOGGING = { 228 | 'version': 1, 229 | 'disable_existing_loggers': False, 230 | 'filters': { 231 | 'require_debug_false': { 232 | '()': 'django.utils.log.RequireDebugFalse' 233 | } 234 | }, 235 | 'handlers': { 236 | 'file': { 237 | 'level': 'ERROR', 238 | 'class': 'logging.FileHandler', 239 | 'formatter': 'verbose', 240 | 'filename': '/var/log/django/error.log', 241 | }, 242 | 'file': { 243 | 'level': 'DEBUG', 244 | 'class': 'logging.FileHandler', 245 | 'formatter': 'verbose', 246 | 'filename': '/var/log/django/debug.log', 247 | }, 248 | 'file': { 249 | 'level': 'INFO', 250 | 'class': 'logging.FileHandler', 251 | 'formatter': 'verbose', 252 | 'filename': '/var/log/django/info.log', 253 | }, 254 | }, 255 | 'formatters': { 256 | 'verbose': { 257 | 'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s' 258 | }, 259 | 'simple': { 260 | 'format': 261 | '%(levelname)s %(message)s' 262 | }, 263 | }, 264 | 'loggers': { 265 | 'django': { 266 | 'handlers':['file'], 267 | 'propagate': True, 268 | 'level':'DEBUG', 269 | }, 270 | 'manifests.models': { 271 | 'handlers': ['file'], 272 | 'level': 'ERROR', 273 | 'propagate': True, 274 | }, 275 | 'pkgs.models': { 276 | 'handlers': ['file'], 277 | 'level': 'INFO', 278 | 'propagate': True, 279 | }, 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /docker-machine-munki-do-start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Munki container variables 4 | # Edit this line to point to your munki_repo. It must be within /Users somewhere: 5 | MUNKI_REPO="/Users/Shared/repo" 6 | # Set the public port on which you wish to access Munki 7 | MUNKI_PORT=8080 8 | # Create a new folder to house the Munki-Do Django database and point to it here. 9 | # If using Docker-Machine, it must be within /Users somewhere: 10 | MUNKI_DO_DB="/Users/Shared/munki-do-db" 11 | # Set the public port on which you wish to access Munki-Do 12 | MUNKI_DO_PORT=8000 13 | # Create a new folder to house the Sal Django database and point to it here. 14 | # If using Docker-Machine, it must be within /Users somewhere: 15 | SAL_DB="/Users/Shared/sal-db" 16 | # Set the public port on which you wish to access Sal 17 | SAL_PORT=8081 18 | # Create a new folder to house the MWA2 Django database and point to it here: 19 | # If using Docker-Machine, it must be within /Users somewhere: 20 | MWA2_DB="/Users/Shared/mwa2-db" 21 | # Set the public port on which you wish to access MWA2 22 | MWA2_PORT=8082 23 | 24 | ## These are MUNKI-DO specific options: 25 | 26 | # Set Munki-Do manifest item search to all items rather than just in current catalog: 27 | ALL_ITEMS=true 28 | # Munki-Do opens on the '/catalog' pages by default. Set to "/pkgs" or "/manifest" if you 29 | # wish to change this behaviour: 30 | LOGIN_REDIRECT_URL="/pkgs" 31 | # Munki-Do timezone is 'Europe/Zurich' by default, but you can change to whatever you 32 | # wish using the codes listed at http://en.wikipedia.org/wiki/List_of_tz_zones_by_name 33 | TIME_ZONE='Europe/Zurich' 34 | # Comment this out or set to '' to disable git 35 | #GIT_PATH='/usr/bin/git' 36 | # Comment this out or leave blank to disable git branching 37 | # (so all commits are done to master branch). 38 | # Or set to any value, e.g.'yes', 'no', 'fred', in order to enable git branching. 39 | GIT_BRANCHING='' 40 | # Comment this out to enable git to track the 'pkgs' directory 41 | # Or set to any value, e.g.'yes', 'no', 'fred', in order to ignore the pkgs directory. 42 | GIT_IGNORE_PKGS='yes' 43 | MANIFEST_RESTRICTION_KEY='restriction' 44 | 45 | ### Gitlab 46 | # Note: volume linking to /Users won't work in OS X due to a permissions issue, 47 | # so needs to be linked to a folder in the boot2docker host. You may wish to back 48 | # this up in case you decide to destroy the docker-machine. 49 | # Comment this out or set as '' if you don't want to build a Gitlab server 50 | # GITLAB_DATA="/home/docker/gitlab-data" 51 | 52 | # set -x #echo on 53 | 54 | # Check that Docker Machine exists 55 | if [ -z "$(docker-machine ls | grep munkido)" ]; then 56 | echo 57 | echo "### WELCOME TO THE MUNKI-DO ALL-IN-ONE INSTALLER" 58 | echo "### Note that Docker-Machine is a development environment." 59 | echo "### Think carefully before using this in Production." 60 | echo 61 | 62 | # docker-machine create -d vmwarefusion --vmwarefusion-disk-size=10000 munkido 63 | docker-machine create -d virtualbox --virtualbox-disk-size=10000 munkido 64 | docker-machine env munkido 65 | eval $(docker-machine env munkido) # this doesn't seem to work from a script. 66 | # we need to modify the ports before we carry on 67 | 68 | echo 69 | echo "### You need to now run the following command in your terminal " 70 | echo "### and then re-run this script, sit back and wait for the magic." 71 | echo "### (try as I might, I cannot get it to work from within the script!)" 72 | echo "eval \$(docker-machine env munkido)" 73 | echo 74 | touch "$HOME/.munki-do-is-new" 75 | exit 0 76 | fi 77 | 78 | # Check that the machine will restart after a reboot 79 | if [ -f "$HOME/Library/LaunchAgents/com.docker.machine.munkido.plist" ]; then 80 | cp "com.docker.machine.munkido.plist" "$HOME/Library/LaunchAgents/" 81 | launchctl load ~/Library/LaunchAgents/com.docker.machine.default.plist 82 | fi 83 | 84 | # Check that Docker Machine is running 85 | if [[ "$(docker-machine status munkido)" != "Running" || -f "$HOME/.munki-do-is-new" ]]; then 86 | # delete port forwarding assignments, in case we've changed them 87 | docker-machine stop munkido 88 | VBoxManage modifyvm "munkido" --natpf1 delete munki-do 89 | VBoxManage modifyvm "munkido" --natpf1 delete munki 90 | VBoxManage modifyvm "munkido" --natpf1 delete mwa2 91 | VBoxManage modifyvm "munkido" --natpf1 delete sal 92 | # setup the required port forwarding on the VM 93 | VBoxManage modifyvm "munkido" --natpf1 "munki-do,tcp,,$MUNKI_DO_PORT,,$MUNKI_DO_PORT" 94 | VBoxManage modifyvm "munkido" --natpf1 "munki,tcp,,$MUNKI_PORT,,$MUNKI_PORT" 95 | VBoxManage modifyvm "munkido" --natpf1 "mwa2,tcp,,$MWA2_PORT,,$MWA2_PORT" 96 | VBoxManage modifyvm "munkido" --natpf1 "sal,tcp,,$SAL_PORT,,$SAL_PORT" 97 | # start the machine 98 | docker-machine restart munkido 99 | rm "$HOME/.munki-do-is-new" 100 | fi 101 | 102 | # Get the IP address of the machine 103 | IP=`docker-machine ip munkido` 104 | 105 | # Clean up 106 | # This checks whether munki munki-do etc are running and stops them 107 | # if so (thanks to Pepijn Bruienne): 108 | docker ps -a | sed "s/\ \{2,\}/$(printf '\t')/g" | \ 109 | awk -F"\t" '/munki|munki-do|mwa2|sal|postgres-sal|gitlab|gitlab-postgresql|gitlab-redis/{print $1}' | \ 110 | xargs docker rm -f 111 | 112 | ## GITLAB settings 113 | 114 | if [ $GITLAB_DATA ]; then 115 | # Gitlab-postgres database 116 | docker run --name gitlab-postgresql -d \ 117 | --env 'DB_NAME=gitlabhq_production' \ 118 | --env 'DB_USER=gitlab' --env 'DB_PASS=password' \ 119 | --volume $GITLAB_DATA/postgresql:/var/lib/postgresql \ 120 | quay.io/sameersbn/postgresql 121 | 122 | # Gitlab Redis instance 123 | # - comment out if you're using an external Git repository or not using Git 124 | docker run --name gitlab-redis -d \ 125 | --volume $GITLAB_DATA/redis:/var/lib/redis \ 126 | quay.io/sameersbn/redis:latest 127 | 128 | # Gitlab - runs on port 10080 129 | docker run --name gitlab -d \ 130 | --link gitlab-postgresql:postgresql --link gitlab-redis:redisio \ 131 | --publish 10022:22 --publish 10080:80 \ 132 | --env 'GITLAB_PORT=10080' --env 'GITLAB_SSH_PORT=10022' \ 133 | --env 'GITLAB_SECRETS_DB_KEY_BASE=sxRfjpqHCfwMBHfrP8NXp5V6gS2wxBLXgv57pdvGKQMQSLTfDzBFfTf2vhQLvrxK' \ 134 | --volume $GITLAB_DATA/gitlab:/home/git/data \ 135 | quay.io/sameersbn/gitlab:8.1.0-2 136 | 137 | # Docker-gitlab - Since ssh-keyscan doesn't generate the 138 | # correct syntax, you need to copy the line directly from your OS X host's known_hosts file 139 | # into the `echo` statement. You must manually make a connection to the git repo in order 140 | # to generate the ssh key: 141 | cat ~/.ssh/known_hosts | grep $IP > docker/known_hosts 142 | 143 | # Note: after first run, you will need to set up your Gitlab repository. This involves: 144 | # # Logging in via a browser (http://IP-address:10080). 145 | # # Default username (root) and password (5iveL!fe). 146 | # # Changing the password 147 | # # Logging in again with the new password 148 | # # Clicking +New Project 149 | # # Setting the project path to 'munki_repo' 150 | # # Select Visibility Level as Public 151 | # # Click Create Project 152 | # # If you haven't already created an ssh key, do so using the hints at http://IP-address:10080/help/ssh/README 153 | # # In Terminal, enter the command 'pbcopy < ~/.ssh/id_rsa.pub' 154 | # # If recreating a destroyed docker-machine, you need to remove the existing entry from 155 | # # ~/.ssh/known_hosts 156 | # # If you aren't on master branch, `git checkout -b origin master` 157 | # # Push the branch you are on using `git push --set-upstream origin master` 158 | fi 159 | ## END of GITLAB settings 160 | 161 | # ensuring the Munki-Do DB folder exists with the correct permissions 162 | if [ ! -d "$MUNKI_DO_DB" ]; then 163 | mkdir -p "$MUNKI_DO_DB" 164 | # chmod and chown if you need to! 165 | fi 166 | 167 | if [ ! -d "$SAL_DB" ]; then 168 | mkdir -p "$SAL_DB" 169 | # chmod and chown if you need to! 170 | fi 171 | 172 | # This isn't needed for Munki-Do to operate, but is needed if you want a working 173 | # Munki server - runs on port 8080 174 | docker run -d --restart=always --name="munki" -v $MUNKI_REPO:/munki_repo \ 175 | -p $MUNKI_PORT:80 -h munki groob/docker-munki 176 | 177 | # This is optional for complicated builds. It's essential if you're using gitlab in the docker-machine. 178 | docker build -t="grahamrpugh/munki-do" . 179 | 180 | 181 | # munki-do container 182 | docker run -d --restart=always --name munki-do \ 183 | -p $MUNKI_DO_PORT:8000 \ 184 | -v $MUNKI_REPO:/munki_repo \ 185 | -v $MUNKI_DO_DB:/munki-do-db \ 186 | -e DOCKER_MUNKIDO_TIME_ZONE="$TIME_ZONE" \ 187 | -e DOCKER_MUNKIDO_LOGIN_REDIRECT_URL="$LOGIN_REDIRECT_URL" \ 188 | -e DOCKER_MUNKIDO_ALL_ITEMS="$ALL_ITEMS" \ 189 | -e DOCKER_MUNKIDO_GIT_PATH="$GIT_PATH" \ 190 | -e DOCKER_MUNKIDO_GIT_BRANCHING="$GIT_BRANCHING" \ 191 | -e DOCKER_MUNKIDO_GIT_IGNORE_PKGS="$GIT_IGNORE_PKGS" \ 192 | -e DOCKER_MUNKIDO_MANIFEST_RESTRICTION_KEY="$MANIFEST_RESTRICTION_KEY" \ 193 | grahamrpugh/munki-do 194 | 195 | 196 | # Bitbucket / Github - use the following two lines to set up the entry in known_hosts 197 | # (edit the domain if looking up github.com): 198 | # docker exec -it munki-do ssh-keygen -R bitbucket.org 199 | # docker exec -it munki-do ssh-keyscan bitbucket.org > /root/.ssh/known_hosts 200 | 201 | # munki-do container 202 | docker run -d --restart=always --name "mwa2" \ 203 | -p $MWA2_PORT:8000 \ 204 | -v $MUNKI_REPO:/munki_repo \ 205 | -v $MWA2_DB:/mwa2-db \ 206 | grahamrpugh/mwa2 207 | 208 | 209 | #sal-server container - runs on port 8081 210 | docker run -d --name="sal" \ 211 | --restart="always" \ 212 | -p $SAL_PORT:8000 \ 213 | -v $SAL_DB:/home/docker/sal/db \ 214 | -e ADMIN_PASS=pass \ 215 | -e DOCKER_SAL_TZ="Europe/Berlin" \ 216 | macadmins/sal 217 | 218 | echo 219 | echo "### Your Docker Machine IP is: $IP" 220 | echo "### Your MunkiWebAdmin2 URL is: http://$IP:$MWA2_PORT" 221 | echo "### Your Munki-Do URL is: http://$IP:$MUNKI_DO_PORT" 222 | echo "### Your Sal URL is: http://$IP:$SAL_PORT" 223 | echo "### Test your Munki URL with: http://$IP:$MUNKI_PORT/repo/catalogs/all" 224 | if [ $GITLAB_DATA ]; then 225 | echo "### Your Gitlab URL is: http://$IP:10080" 226 | fi 227 | echo 228 | 229 | 230 | -------------------------------------------------------------------------------- /munkido/site_static/js/plugins/dataTables/dataTables.bootstrap.js: -------------------------------------------------------------------------------- 1 | /* Set the defaults for DataTables initialisation */ 2 | $.extend(true, $.fn.dataTable.defaults, { 3 | "sDom": "<'row'<'col-sm-6'l><'col-sm-6'f>r>" + "t" + "<'row'<'col-sm-6'i><'col-sm-6'p>>", 4 | "oLanguage": { 5 | "sLengthMenu": "_MENU_ records per page" 6 | } 7 | }); 8 | 9 | 10 | /* Default class modification */ 11 | $.extend($.fn.dataTableExt.oStdClasses, { 12 | "sWrapper": "dataTables_wrapper form-inline", 13 | "sFilterInput": "form-control input-sm", 14 | "sLengthSelect": "form-control input-sm" 15 | }); 16 | 17 | // In 1.10 we use the pagination renderers to draw the Bootstrap paging, 18 | // rather than custom plug-in 19 | if ($.fn.dataTable.Api) { 20 | $.fn.dataTable.defaults.renderer = 'bootstrap'; 21 | $.fn.dataTable.ext.renderer.pageButton.bootstrap = function(settings, host, idx, buttons, page, pages) { 22 | var api = new $.fn.dataTable.Api(settings); 23 | var classes = settings.oClasses; 24 | var lang = settings.oLanguage.oPaginate; 25 | var btnDisplay, btnClass; 26 | 27 | var attach = function(container, buttons) { 28 | var i, ien, node, button; 29 | var clickHandler = function(e) { 30 | e.preventDefault(); 31 | if (e.data.action !== 'ellipsis') { 32 | api.page(e.data.action).draw(false); 33 | } 34 | }; 35 | 36 | for (i = 0, ien = buttons.length; i < ien; i++) { 37 | button = buttons[i]; 38 | 39 | if ($.isArray(button)) { 40 | attach(container, button); 41 | } else { 42 | btnDisplay = ''; 43 | btnClass = ''; 44 | 45 | switch (button) { 46 | case 'ellipsis': 47 | btnDisplay = '…'; 48 | btnClass = 'disabled'; 49 | break; 50 | 51 | case 'first': 52 | btnDisplay = lang.sFirst; 53 | btnClass = button + (page > 0 ? 54 | '' : ' disabled'); 55 | break; 56 | 57 | case 'previous': 58 | btnDisplay = lang.sPrevious; 59 | btnClass = button + (page > 0 ? 60 | '' : ' disabled'); 61 | break; 62 | 63 | case 'next': 64 | btnDisplay = lang.sNext; 65 | btnClass = button + (page < pages - 1 ? 66 | '' : ' disabled'); 67 | break; 68 | 69 | case 'last': 70 | btnDisplay = lang.sLast; 71 | btnClass = button + (page < pages - 1 ? 72 | '' : ' disabled'); 73 | break; 74 | 75 | default: 76 | btnDisplay = button + 1; 77 | btnClass = page === button ? 78 | 'active' : ''; 79 | break; 80 | } 81 | 82 | if (btnDisplay) { 83 | node = $('
  • ', { 84 | 'class': classes.sPageButton + ' ' + btnClass, 85 | 'aria-controls': settings.sTableId, 86 | 'tabindex': settings.iTabIndex, 87 | 'id': idx === 0 && typeof button === 'string' ? settings.sTableId + '_' + button : null 88 | }) 89 | .append($('', { 90 | 'href': '#' 91 | }) 92 | .html(btnDisplay) 93 | ) 94 | .appendTo(container); 95 | 96 | settings.oApi._fnBindAction( 97 | node, { 98 | action: button 99 | }, clickHandler 100 | ); 101 | } 102 | } 103 | } 104 | }; 105 | 106 | attach( 107 | $(host).empty().html('