Skip to content
This repository has been archived by the owner on Aug 22, 2022. It is now read-only.

Commit

Permalink
Merge branch 'master' into logging-handler
Browse files Browse the repository at this point in the history
  • Loading branch information
antoviaque committed Sep 27, 2015
2 parents 8fc9bd3 + 318b77f commit 9b289b1
Show file tree
Hide file tree
Showing 19 changed files with 615 additions and 81 deletions.
55 changes: 49 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,20 +1,48 @@
# Config
# OpenCraft -- tools to aid developing and hosting free software projects
# Copyright (C) 2015 OpenCraft <xavier@opencraft.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

# Config ######################################################################

WORKERS = 4
SHELL = /bin/bash


# Parameters ##################################################################

# For `test_one` use the rest as arguments and turn them into do-nothing targets
ifeq (test_one,$(firstword $(MAKECMDGOALS)))
RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
$(eval $(RUN_ARGS):;@:)
endif


# Commands ####################################################################

all:
rundev

clean:
find -name '*.pyc' -delete
find -name '*~' -delete
find -name '__pycache__' -type d -delete
rm -rf .coverage build
find static/js/external -type f -not -name 'Makefile' -not -name '.gitignore' -delete

collectstatic: clean
collectstatic: clean js_external
honcho run ./manage.py collectstatic --noinput

migrate: clean
Expand All @@ -26,12 +54,18 @@ migration_check: clean
run: clean migration_check collectstatic
honcho start --concurrency "worker=$(WORKERS)"

rundev: clean migration_check
rundev: clean migration_check js_external
honcho start -f Procfile.dev

shell:
honcho run ./manage.py shell_plus

upgrade_dependencies:
pip freeze --local | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U


# Tests #######################################################################

test_prospector: clean
prospector --profile opencraft

Expand All @@ -49,11 +83,20 @@ test_integration: clean
echo -e "\nIntegration tests skipped (create a '.env.integration' file to run them)" ; \
fi

test: clean test_prospector test_unit test_integration
test_js: clean js_external
cd instance/tests/js && jasmine-ci --logs --browser firefox

test_js_web: clean js_external
cd instance/tests/js && jasmine --host 0.0.0.0

test: clean test_prospector test_unit test_js test_integration
@echo -e "\nAll tests OK!\n"

test_one: clean
honcho -e .env.test run ./manage.py test $(RUN_ARGS)

upgrade_dependencies:
pip freeze --local | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U

# Files #######################################################################

js_external:
$(MAKE) -C static/js/external
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,14 +168,18 @@ To run a single test, use `make test_one`:
$ make test_one instance.tests.models.test_server
```

You can also run prospector and the unit tests independently:
You can also run prospector, the unit tests, JS tests and integration independently:

```
$ make test_prospector
$ make test_unit
$ make test_js
$ make test_integration
```

JS tests can be run in your browser for debugging (see `make test_js_web` and then go to
http://localhost:8888/ ), or in a CI manner via selenium and `jasmine-ci` (see `make test_js`).

Note that the integration tests aren't run by default, as they require a working
OpenStack cluster configured. To run them, create a `.env.integration` file -
your development environment is likely a good starting point:
Expand Down
8 changes: 8 additions & 0 deletions Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,16 @@ Vagrant.configure(2) do |config|
config.vm.box = 'ubuntu/trusty64'
config.vm.network 'forwarded_port', guest: 2001, host: 2001
config.vm.network 'forwarded_port', guest: 5000, host: 5000
config.vm.network 'forwarded_port', guest: 8888, host: 8888
config.ssh.forward_x11 = true
config.vm.provision 'shell',
inline: PROVISION,
privileged: false,
keep_color: true

config.vm.provider :virtualbox do |vb|
# Allow DNS to work for Ubuntu host
# http://askubuntu.com/questions/238040/how-do-i-fix-name-service-for-vagrant-client
vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
end
end
1 change: 1 addition & 0 deletions debian_packages.lst
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ python3-pip
libpq-dev
python-dev
redis-server
firefox
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

(function(){
"use strict";


// App configuration //////////////////////////////////////////////////////////

var app = angular.module('InstanceApp', [
Expand Down Expand Up @@ -44,61 +44,42 @@ app.config(function($stateProvider, $urlRouterProvider, RestangularProvider) {
url: "/",
templateUrl: "/static/html/instance/index.html",
controller: "Index"
})
});
});


// Services ///////////////////////////////////////////////////////////////////

// Services
app.factory('OpenCraftAPI', function(Restangular) {
return Restangular.withConfig(function(RestangularConfigurer) {
RestangularConfigurer.setBaseUrl('/api/v1');
});
});


// Function ///////////////////////////////////////////////////////////////////

function updateInstanceList($scope, OpenCraftAPI) {
// Display loading message
$scope.loading = true;

OpenCraftAPI.all("openedxinstance").getList().then(function(instanceList) {
console.log('Updating instance list', instanceList);
$scope.instanceList = instanceList;

if($scope.selected.instance){
var updated_instance = null;
_.each(instanceList, function(instance) {
if(instance.id === $scope.selected.instance.id) {
updated_instance = instance;
}
});
$scope.selected.instance = updated_instance;
}
}, function(response) {
console.log('Error from server: ', response);
}).finally(function () {
$scope.loading = false;
});
}


// Controllers ////////////////////////////////////////////////////////////////

app.controller("Index", ['$scope', 'Restangular', 'OpenCraftAPI', '$q',
function ($scope, Restangular, OpenCraftAPI, $q) {
// Display loading message
$scope.loading = true;

// Selection
$scope.selected = Array();
$scope.init = function() {
$scope.loading = true;
$scope.selected = {};

$scope.updateInstanceList();

// Init websockets
swampdragon.onChannelMessage($scope.handleChannelMessage);
swampdragon.ready(function() {
swampdragon.subscribe('notifier', 'notification', null);
swampdragon.subscribe('notifier', 'log', null);
});
};

$scope.select = function(selection_type, value) {
$scope.selected[selection_type] = value;
console.log('Selected ' + selection_type + ':', value);
};

// Reprovisioning
$scope.provision = function(instance) {
console.log('Provisioning instance', instance);
instance.status = 'terminating';
Expand All @@ -107,29 +88,48 @@ app.controller("Index", ['$scope', 'Restangular', 'OpenCraftAPI', '$q',
server.status = 'terminating';
}
});
instance.post("provision");
return instance.post("provision");
};

// Retrieve instance list
updateInstanceList($scope, OpenCraftAPI);
$scope.updateInstanceList = function() {
$scope.loading = true; // Display loading message

// Intialize websockets
swampdragon.onChannelMessage(function(channels, message) {
return OpenCraftAPI.all("openedxinstance").getList().then(function(instanceList) {
console.log('Updating instance list', instanceList);
$scope.instanceList = instanceList;

if($scope.selected.instance){
var updated_instance = null;
_.each(instanceList, function(instance) {
if(instance.id === $scope.selected.instance.id) {
updated_instance = instance;
}
});
$scope.selected.instance = updated_instance;
}
}, function(response) {
console.log('Error from server: ', response);
}).finally(function () {
$scope.loading = false;
});
};

$scope.handleChannelMessage = function(channels, message) {
console.log('Received websocket message', channels, message.data);

if(message.data.type === 'server_update') {
updateInstanceList($scope, OpenCraftAPI);
$scope.updateInstanceList();
} else if(message.data.type === 'instance_log') {
if($scope.selected.instance && $scope.selected.instance.id === message.data.instance_id) {
$scope.$apply(function(){
$scope.selected.instance.log_text += message.data.log_entry + '\n';
});
}
}
});
swampdragon.ready(function() {
swampdragon.subscribe('notifier', 'notification', null);
swampdragon.subscribe('notifier', 'log', null);
});
};

$scope.init();
}
]);

})();
2 changes: 1 addition & 1 deletion instance/templates/instance/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@
{% block body_js %}
{% swampdragon_settings %}
<script src="{% static 'swampdragon/js/dist/swampdragon.min.js' %}"></script>
<script src="{% static "js/instance.js" %}"></script>
<script src="{% static "js/src/instance.js" %}"></script>
{% endblock body_js %}
61 changes: 61 additions & 0 deletions instance/tests/fixtures/api/instances_list.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
[
{
"id": 2,
"api_url": "http://localhost:5000/api/v1/openedxinstance/2/",
"active_server_set": [
{
"id": 23,
"api_url": "http://localhost:5000/api/v1/openstackserver/23/",
"created": "2015-08-20T06:40:18.835733Z",
"instance": "http://localhost:5000/api/v1/openedxinstance/2/",
"modified": "2015-08-20T12:12:34.781802Z",
"openstack_id": "f889c46a-975a-4ecb-acb8-b6c3c5f97c8e",
"status": "ready"
}
],
"base_domain": "opencraft.com",
"branch_name": "master",
"commit_id": "24bca27b46a0e65c00628716a77d19a6c5aecd55",
"created": "2015-08-08T07:22:56.062796Z",
"domain": "tmp.sandbox.opencraft.com",
"email": "contact@example.com",
"github_base_url": "https://github.com/antoviaque/edx-platform",
"github_branch_url": "https://github.com/antoviaque/edx-platform/tree/master",
"log_text": "2015-08-08 07:23:16 [info] Terminate servers for instance tmp.sandbox - antoviaque/edx-platform/master (24bca27) (http://tmp.sandbox.opencraft.com/)...\n2015-08-08 07:23:16 [info] Start new server for instance tmp.sandbox - antoviaque/edx-platform/master (24bca27) (http://tmp.sandbox.opencraft.com/)...\n2015-08-08 07:23:18 [info] Waiting for IP assignment on server 3841c324-c004-4188-9d8c-f1071cd635c5...\n"
},
{
"id": 1,
"api_url": "http://localhost:5000/api/v1/openedxinstance/1/",
"active_server_set": [
{
"id": 19,
"api_url": "http://localhost:5000/api/v1/openstackserver/19/",
"created": "2015-08-18T05:48:55.163364Z",
"instance": "http://localhost:5000/api/v1/openedxinstance/1/",
"modified": "2015-08-18T05:48:56.360140Z",
"openstack_id": "c007b320-1643-4f95-838a-1467ab0927e7",
"status": "started"
}
],
"base_domain": "opencraft.com",
"branch_name": "OC-791-course-timeline",
"commit_id": "40952060bc7573c5035620b985b211a24360f311",
"created": "2015-08-07T18:10:56.823929Z",
"domain": "pr2.sandbox.opencraft.com",
"email": "contact@example.com",
"github_base_url": "https://github.com/antoviaque/edx-platform",
"github_branch_url": "https://github.com/antoviaque/edx-platform/tree/OC-791-course-timeline",
"log_text": "2015-08-07 18:10:56 [info] Terminate servers for instance PR#2: Display start date, end date, and number of sections (weeks) on \"Course Info\" tab of instructor dashboard. (antoviaque) - antoviaque/edx-platform/OC-791-course-timeline (4095206) (http://pr2.sandbox.opencraft.com/)...\n",
"github_organization_name": "antoviaque",
"modified": "2015-08-18T05:48:54.356884Z",
"name": "PR#2: Display start date, end date, and number of sections (weeks) on \"Course Info\" tab of instructor dashboard. (antoviaque) - antoviaque/edx-platform/OC-791-course-timeline (4095206)",
"protocol": "http",
"repository_url": "https://github.com/antoviaque/edx-platform.git",
"status": "started",
"studio_url": "http://studio.pr2.sandbox.opencraft.com/",
"sub_domain": "pr2.sandbox",
"url": "http://pr2.sandbox.opencraft.com/",
"updates_feed": "https://github.com/antoviaque/edx-platform/commits/OC-791-course-timeline.atom",
"vars_str": "# System\nCOMMON_HOSTNAME: 'pr2.sandbox.opencraft.com'\n\n# edxapp\nEDXAPP_PLATFORM_NAME: \"PR#2: Display start date, end date, and number of sections (weeks) on &quot;Course Info&quot; tab of instructor dashboard. (antoviaque) - antoviaque/edx-platform/OC-791-course-timeline (4095206)\"\nEDXAPP_LMS_NGINX_PORT: 80\nEDXAPP_LMS_PREVIEW_NGINX_PORT: 80\nEDXAPP_CMS_NGINX_PORT: 80\nEDXAPP_SITE_NAME: 'pr2.sandbox.opencraft.com'\nEDXAPP_LMS_SITE_NAME: 'pr2.sandbox.opencraft.com'\nEDXAPP_LMS_BASE: 'pr2.sandbox.opencraft.com'\nEDXAPP_PREVIEW_LMS_BASE: 'pr2.sandbox.opencraft.com'\n\nEDXAPP_CMS_SITE_NAME: 'studio.pr2.sandbox.opencraft.com'\nEDXAPP_CMS_BASE: 'studio.pr2.sandbox.opencraft.com'\n\n# Forum environment settings\nFORUM_RACK_ENV: 'production'\nFORUM_SINATRA_ENV: 'production'\n\n# Emails\nEDXAPP_CONTACT_EMAIL: 'contact@example.com'\nEDXAPP_TECH_SUPPORT_EMAIL: 'contact@example.com'\nEDXAPP_BUGS_EMAIL: 'contact@example.com'\nEDXAPP_FEEDBACK_SUBMISSION_EMAIL: 'contact@example.com'\nEDXAPP_DEFAULT_FROM_EMAIL: 'contact@example.com'\nEDXAPP_DEFAULT_FEEDBACK_EMAIL: 'contact@example.com'\nEDXAPP_SERVER_EMAIL: 'contact@example.com'\nEDXAPP_BULK_EMAIL_DEFAULT_FROM_EMAIL: 'contact@example.com'\n\n# Misc\nEDXAPP_TIME_ZONE: 'UTC'\n\n# Security updates\nCOMMON_SECURITY_UPDATES: true\nSECURITY_UNATTENDED_UPGRADES: true\nSECURITY_UPDATE_ALL_PACKAGES: false\nSECURITY_UPGRADE_ON_ANSIBLE: true\n\n# Repositories URLs\nedx_ansible_source_repo: 'https://github.com/edx/configuration.git'\nedx_platform_repo: 'https://github.com/antoviaque/edx-platform.git'\n\n# Pin down dependencies to specific (known to be compatible) commits.\nedx_platform_version: '40952060bc7573c5035620b985b211a24360f311'\nconfiguration_version: 'master'\nforum_version: 'master'\nnotifier_version: 'master'\nxqueue_version: 'master'\ncerts_version: 'master'\n\n# Features\nEDXAPP_FEATURES:\n USE_MICROSITES: false\n AUTH_USE_OPENID: false\n ENABLE_DISCUSSION_SERVICE: true\n ENABLE_INSTRUCTOR_ANALYTICS: true\n ENABLE_INSTRUCTOR_EMAIL: true\n REQUIRE_COURSE_EMAIL_AUTH: false\n ENABLE_PEARSON_HACK_TEST: false\n SUBDOMAIN_BRANDING: false\n SUBDOMAIN_COURSE_LISTINGS: false\n PREVIEW_LMS_BASE: 'pr2.sandbox.opencraft.com'\n ENABLE_DJANGO_ADMIN_SITE: true\n ALLOW_ALL_ADVANCED_COMPONENTS: true\n\n\n"
}
]
28 changes: 28 additions & 0 deletions instance/tests/js/helpers/fixtures.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// OpenCraft -- tools to aid developing and hosting free software projects
// Copyright (C) 2015 OpenCraft <xavier@opencraft.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

(function(){
"use strict";

// Functions //////////////////////////////////////////////////////////////////

// Load the JS object from a JSON fixture
jasmine.loadFixture = function(fixturePath) {
var fixtureJSON = jasmine.httpGET('/__src__/instance/tests/fixtures/' + fixturePath);
return JSON.parse(fixtureJSON);
};

})();
Loading

0 comments on commit 9b289b1

Please sign in to comment.