bosh-director 1.3202.0 → 1.3213.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/db/migrations/director/20151223172000_rename_requires_json.rb +7 -0
- data/db/migrations/director/20160106162749_runtime_configs.rb +19 -0
- data/db/migrations/director/20160106163433_add_runtime_configs_to_deployments.rb +7 -0
- data/db/migrations/director/20160202162216_add_post_start_completed_to_instance.rb +7 -0
- data/db/migrations/director/20160210201838_denormalize_compiled_package_stemcell_id_to_stemcell_name_and_version.rb +57 -0
- data/db/migrations/director/20160219175840_add_column_teams_to_deployments.rb +8 -0
- data/db/migrations/director/20160224222508_add_deployment_name_to_task.rb +7 -0
- data/db/migrations/director/20160225182206_rename_post_start_completed.rb +8 -0
- data/lib/bosh/director.rb +9 -0
- data/lib/bosh/director/api.rb +1 -1
- data/lib/bosh/director/api/api_helper.rb +27 -0
- data/lib/bosh/director/api/controllers/base_controller.rb +28 -5
- data/lib/bosh/director/api/controllers/cloud_configs_controller.rb +4 -3
- data/lib/bosh/director/api/controllers/deployments_controller.rb +165 -81
- data/lib/bosh/director/api/controllers/locks_controller.rb +1 -1
- data/lib/bosh/director/api/controllers/packages_controller.rb +4 -35
- data/lib/bosh/director/api/controllers/releases_controller.rb +6 -4
- data/lib/bosh/director/api/controllers/runtime_configs_controller.rb +41 -0
- data/lib/bosh/director/api/controllers/stemcells_controller.rb +1 -1
- data/lib/bosh/director/api/controllers/tasks_controller.rb +72 -5
- data/lib/bosh/director/api/deployment_manager.rb +10 -42
- data/lib/bosh/director/api/extensions/scoping.rb +11 -24
- data/lib/bosh/director/api/instance_lookup.rb +10 -22
- data/lib/bosh/director/api/instance_manager.rb +27 -15
- data/lib/bosh/director/api/local_identity_provider.rb +0 -8
- data/lib/bosh/director/api/problem_manager.rb +7 -19
- data/lib/bosh/director/api/property_manager.rb +12 -21
- data/lib/bosh/director/api/resurrector_manager.rb +4 -4
- data/lib/bosh/director/api/route_configuration.rb +1 -0
- data/lib/bosh/director/api/runtime_config_manager.rb +35 -0
- data/lib/bosh/director/api/snapshot_manager.rb +2 -2
- data/lib/bosh/director/api/task_helper.rb +2 -1
- data/lib/bosh/director/api/task_manager.rb +2 -8
- data/lib/bosh/director/api/uaa_identity_provider.rb +0 -16
- data/lib/bosh/director/blob_util.rb +3 -2
- data/lib/bosh/director/cloudcheck_helper.rb +17 -3
- data/lib/bosh/director/compile_task.rb +53 -24
- data/lib/bosh/director/compile_task_generator.rb +6 -6
- data/lib/bosh/director/compiled_package_group.rb +4 -3
- data/lib/bosh/director/compiled_release.rb +6 -0
- data/lib/bosh/director/compiled_release/manifest.rb +30 -0
- data/lib/bosh/director/compiled_release_manifest.rb +3 -3
- data/lib/bosh/director/config.rb +11 -1
- data/lib/bosh/director/deployment_plan.rb +1 -0
- data/lib/bosh/director/deployment_plan/assembler.rb +6 -2
- data/lib/bosh/director/deployment_plan/cloud_manifest_parser.rb +26 -10
- data/lib/bosh/director/deployment_plan/compilation_config.rb +43 -7
- data/lib/bosh/director/deployment_plan/compilation_instance_pool.rb +10 -3
- data/lib/bosh/director/deployment_plan/deployment_repo.rb +4 -10
- data/lib/bosh/director/deployment_plan/dynamic_network.rb +1 -1
- data/lib/bosh/director/deployment_plan/instance.rb +36 -17
- data/lib/bosh/director/deployment_plan/instance_plan.rb +13 -2
- data/lib/bosh/director/deployment_plan/instance_spec.rb +12 -4
- data/lib/bosh/director/deployment_plan/job.rb +73 -39
- data/lib/bosh/director/deployment_plan/job_availability_zone_parser.rb +4 -4
- data/lib/bosh/director/deployment_plan/job_migrator.rb +7 -7
- data/lib/bosh/director/deployment_plan/job_network_parser.rb +6 -6
- data/lib/bosh/director/deployment_plan/job_spec_parser.rb +91 -33
- data/lib/bosh/director/deployment_plan/links/link.rb +9 -4
- data/lib/bosh/director/deployment_plan/links/link_lookup.rb +23 -15
- data/lib/bosh/director/deployment_plan/links/link_path.rb +168 -15
- data/lib/bosh/director/deployment_plan/links/links_resolver.rb +34 -32
- data/lib/bosh/director/deployment_plan/links/template_link.rb +28 -8
- data/lib/bosh/director/deployment_plan/manifest_validator.rb +1 -1
- data/lib/bosh/director/deployment_plan/network_settings.rb +27 -13
- data/lib/bosh/director/deployment_plan/package_validator.rb +9 -5
- data/lib/bosh/director/deployment_plan/placement_planner/networks_to_static_ips.rb +4 -4
- data/lib/bosh/director/deployment_plan/planner.rb +31 -7
- data/lib/bosh/director/deployment_plan/planner_factory.rb +147 -6
- data/lib/bosh/director/deployment_plan/runtime_manifest_parser.rb +142 -0
- data/lib/bosh/director/deployment_plan/stemcell.rb +2 -2
- data/lib/bosh/director/deployment_plan/steps/package_compile_step.rb +3 -2
- data/lib/bosh/director/deployment_plan/template.rb +93 -8
- data/lib/bosh/director/deployment_plan/update_config.rb +10 -0
- data/lib/bosh/director/deployment_plan/vm_extension.rb +27 -0
- data/lib/bosh/director/errand/runner.rb +1 -1
- data/lib/bosh/director/errors.rb +11 -1
- data/lib/bosh/director/instance_updater.rb +46 -57
- data/lib/bosh/director/instance_updater/instance_state.rb +9 -0
- data/lib/bosh/director/instance_updater/state_applier.rb +18 -5
- data/lib/bosh/director/job_queue.rb +2 -2
- data/lib/bosh/director/job_renderer.rb +2 -2
- data/lib/bosh/director/job_updater.rb +7 -1
- data/lib/bosh/director/jobs/attach_disk.rb +2 -2
- data/lib/bosh/director/jobs/cloud_check/apply_resolutions.rb +6 -1
- data/lib/bosh/director/jobs/cloud_check/scan_and_fix.rb +14 -3
- data/lib/bosh/director/jobs/export_release.rb +1 -1
- data/lib/bosh/director/jobs/fetch_logs.rb +1 -4
- data/lib/bosh/director/jobs/helpers/compiled_package_deleter.rb +1 -2
- data/lib/bosh/director/jobs/helpers/stemcell_deleter.rb +0 -16
- data/lib/bosh/director/jobs/release/release_job.rb +7 -7
- data/lib/bosh/director/jobs/run_errand.rb +5 -5
- data/lib/bosh/director/jobs/ssh.rb +3 -3
- data/lib/bosh/director/jobs/update_deployment.rb +41 -5
- data/lib/bosh/director/jobs/update_release.rb +78 -82
- data/lib/bosh/director/jobs/update_stemcell.rb +1 -1
- data/lib/bosh/director/jobs/vm_state.rb +34 -21
- data/lib/bosh/director/key_generator.rb +54 -0
- data/lib/bosh/director/lock.rb +2 -2
- data/lib/bosh/director/log_bundles_cleaner.rb +1 -0
- data/lib/bosh/director/manifest/changeset.rb +39 -22
- data/lib/bosh/director/manifest/diff_lines.rb +1 -27
- data/lib/bosh/director/manifest/manifest.rb +22 -7
- data/lib/bosh/director/manifest/redactor.rb +44 -0
- data/lib/bosh/director/models.rb +1 -0
- data/lib/bosh/director/models/compiled_package.rb +21 -15
- data/lib/bosh/director/models/deployment.rb +10 -0
- data/lib/bosh/director/models/instance.rb +2 -1
- data/lib/bosh/director/models/release_version.rb +0 -16
- data/lib/bosh/director/models/runtime_config.rb +19 -0
- data/lib/bosh/director/models/template.rb +4 -4
- data/lib/bosh/director/package_dependencies_manager.rb +22 -0
- data/lib/bosh/director/password_helper.rb +18 -0
- data/lib/bosh/director/permission_authorizer.rb +50 -30
- data/lib/bosh/director/post_deployment_script_runner.rb +40 -0
- data/lib/bosh/director/problem_handlers/missing_disk.rb +2 -2
- data/lib/bosh/director/problem_resolver.rb +8 -2
- data/lib/bosh/director/problem_scanner/scanner.rb +1 -1
- data/lib/bosh/director/problem_scanner/vm_scan_stage.rb +1 -1
- data/lib/bosh/director/validation_helper.rb +5 -5
- data/lib/bosh/director/version.rb +1 -1
- data/lib/bosh/director/vm_creator.rb +8 -0
- data/lib/cloud/dummy.rb +1 -0
- metadata +51 -19
- data/lib/bosh/director/api/vm_state_manager.rb +0 -9
- data/lib/bosh/director/compiled_package/blob_sha_mismatch_error.rb +0 -5
- data/lib/bosh/director/compiled_package/compiled_package.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 80b916377f341047163e53997092a6df6ae2129e
|
4
|
+
data.tar.gz: ac33c1cd3698034c745895a8f60fd09dfd759e1a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36df0a755fa74b497cde0c4e87c5c88f64b43cc63d384edd29e63675a5029bb95824f881c5910c6eb823fe723e1c28a1245faccaa4ce26be30fd306bc56c94e4
|
7
|
+
data.tar.gz: 1b1f672cb69232dad861cb533f8da0d1ff03664dd771a24dc245b65246ee3b8275938ece8172006c21f35f06f1d8237579ba3bfab87aeb8a11df35b8f61b1262
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Sequel.migration do
|
2
|
+
change do
|
3
|
+
adapter_scheme = self.adapter_scheme
|
4
|
+
|
5
|
+
create_table :runtime_configs do
|
6
|
+
primary_key :id
|
7
|
+
|
8
|
+
if [:mysql2, :mysql].include?(adapter_scheme)
|
9
|
+
longtext :properties
|
10
|
+
else
|
11
|
+
text :properties
|
12
|
+
end
|
13
|
+
|
14
|
+
Time :created_at, null: false
|
15
|
+
|
16
|
+
index :created_at
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
Sequel.migration do
|
2
|
+
change do
|
3
|
+
alter_table(:compiled_packages) do
|
4
|
+
add_column :stemcell_os, String
|
5
|
+
add_column :stemcell_version, String
|
6
|
+
end
|
7
|
+
|
8
|
+
self[:compiled_packages].each do |compiled_package|
|
9
|
+
next unless compiled_package[:stemcell_id]
|
10
|
+
|
11
|
+
stemcell = self[:stemcells].filter(id: compiled_package[:stemcell_id]).first
|
12
|
+
stemcell_os = stemcell[:operating_system].to_s.empty? ? stemcell[:name] : stemcell[:operating_system]
|
13
|
+
|
14
|
+
self[:compiled_packages].filter(id: compiled_package[:id]).update(
|
15
|
+
stemcell_os: stemcell_os,
|
16
|
+
stemcell_version: stemcell[:version]
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
if [:mysql2, :mysql, :postgres].include?(adapter_scheme)
|
21
|
+
stemcell_foreign_keys = foreign_key_list(:compiled_packages).select { |constraint| constraint.fetch(:columns).include?(:stemcell_id) }
|
22
|
+
raise 'Failed to run migration, found more than 1 stemcell foreign key' if stemcell_foreign_keys.size != 1
|
23
|
+
stemcell_foreign_key_name = stemcell_foreign_keys.first.fetch(:name)
|
24
|
+
|
25
|
+
build_indexes = indexes(:compiled_packages).select { |_, value| value.fetch(:columns) == [:package_id, :stemcell_id, :build] }
|
26
|
+
raise 'Failed to run migration, found more than 1 build index' if build_indexes.size != 1
|
27
|
+
# build_indexes is an array, where each element is an array with first element being the name of index
|
28
|
+
build_index = build_indexes.first.first
|
29
|
+
|
30
|
+
stemcell_indexes = indexes(:compiled_packages).select { |_, value| value.fetch(:columns) == [:package_id, :stemcell_id, :dependency_key_sha1]}
|
31
|
+
raise 'Failed to run migration, found more than 1 stemcell_id index' if stemcell_indexes.size != 1
|
32
|
+
# stemcell_indexes is an array, where each element is an array with first element being the name of index
|
33
|
+
stemcell_index = stemcell_indexes.first.first
|
34
|
+
|
35
|
+
if [:mysql2, :mysql].include?(adapter_scheme)
|
36
|
+
alter_table(:compiled_packages) do
|
37
|
+
drop_index(nil, name: build_index)
|
38
|
+
end
|
39
|
+
elsif [:postgres].include?(adapter_scheme)
|
40
|
+
alter_table(:compiled_packages) do
|
41
|
+
drop_constraint(build_index)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
alter_table(:compiled_packages) do
|
46
|
+
drop_constraint(stemcell_foreign_key_name, :type => :foreign_key)
|
47
|
+
add_index [:package_id, :stemcell_os, :stemcell_version, :build], unique: true, name: 'package_stemcell_build_idx'
|
48
|
+
add_index [:package_id, :stemcell_os, :stemcell_version, :dependency_key_sha1], unique: true, name: 'package_stemcell_dependency_idx'
|
49
|
+
drop_index(nil, name: stemcell_index)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
alter_table(:compiled_packages) do
|
54
|
+
drop_column :stemcell_id
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/bosh/director.rb
CHANGED
@@ -59,15 +59,20 @@ require 'bosh/director/blob_util'
|
|
59
59
|
require 'bosh/director/agent_client'
|
60
60
|
require 'cloud'
|
61
61
|
require 'bosh/director/compile_task'
|
62
|
+
require 'bosh/director/key_generator'
|
63
|
+
require 'bosh/director/package_dependencies_manager'
|
64
|
+
|
62
65
|
require 'bosh/director/job_renderer'
|
63
66
|
require 'bosh/director/cycle_helper'
|
64
67
|
require 'bosh/director/encryption_helper'
|
68
|
+
require 'bosh/director/password_helper'
|
65
69
|
require 'bosh/director/vm_creator'
|
66
70
|
require 'bosh/director/vm_recreator'
|
67
71
|
require 'bosh/director/vm_deleter'
|
68
72
|
require 'bosh/director/vm_metadata_updater'
|
69
73
|
require 'bosh/director/instance_reuser'
|
70
74
|
require 'bosh/director/deployment_plan'
|
75
|
+
require 'bosh/director/compiled_release'
|
71
76
|
require 'bosh/director/errand'
|
72
77
|
require 'bosh/director/duration'
|
73
78
|
require 'bosh/director/hash_string_vals'
|
@@ -75,6 +80,7 @@ require 'bosh/director/instance_deleter'
|
|
75
80
|
require 'bosh/director/instance_updater'
|
76
81
|
require 'bosh/director/instance_updater/preparer'
|
77
82
|
require 'bosh/director/instance_updater/state_applier'
|
83
|
+
require 'bosh/director/instance_updater/instance_state'
|
78
84
|
require 'bosh/director/disk_manager'
|
79
85
|
require 'bosh/director/stopper'
|
80
86
|
require 'bosh/director/job_runner'
|
@@ -86,6 +92,7 @@ require 'bosh/director/nats_rpc'
|
|
86
92
|
require 'bosh/director/network_reservation'
|
87
93
|
require 'bosh/director/problem_scanner/scanner'
|
88
94
|
require 'bosh/director/problem_resolver'
|
95
|
+
require 'bosh/director/post_deployment_script_runner'
|
89
96
|
require 'bosh/director/error_ignorer'
|
90
97
|
require 'bosh/director/deployment_deleter'
|
91
98
|
require 'bosh/director/permission_authorizer'
|
@@ -94,6 +101,7 @@ require 'bosh/director/sequel'
|
|
94
101
|
require 'common/thread_pool'
|
95
102
|
|
96
103
|
require 'bosh/director/manifest/manifest'
|
104
|
+
require 'bosh/director/manifest/redactor'
|
97
105
|
require 'bosh/director/manifest/changeset'
|
98
106
|
require 'bosh/director/manifest/diff_lines'
|
99
107
|
|
@@ -168,6 +176,7 @@ require 'bosh/director/api/controllers/tasks_controller'
|
|
168
176
|
require 'bosh/director/api/controllers/task_controller'
|
169
177
|
require 'bosh/director/api/controllers/users_controller'
|
170
178
|
require 'bosh/director/api/controllers/cloud_configs_controller'
|
179
|
+
require 'bosh/director/api/controllers/runtime_configs_controller'
|
171
180
|
require 'bosh/director/api/controllers/locks_controller'
|
172
181
|
require 'bosh/director/api/controllers/restore_controller'
|
173
182
|
require 'bosh/director/api/route_configuration'
|
data/lib/bosh/director/api.rb
CHANGED
@@ -23,11 +23,11 @@ require 'bosh/director/api/task_manager'
|
|
23
23
|
require 'bosh/director/api/user/config_user_manager'
|
24
24
|
require 'bosh/director/api/user/database_user_manager'
|
25
25
|
require 'bosh/director/api/user/user_manager_provider'
|
26
|
-
require 'bosh/director/api/vm_state_manager'
|
27
26
|
require 'bosh/director/api/backup_manager'
|
28
27
|
require 'bosh/director/api/resurrector_manager'
|
29
28
|
require 'bosh/director/api/restore_manager'
|
30
29
|
require 'bosh/director/api/cloud_config_manager'
|
30
|
+
require 'bosh/director/api/runtime_config_manager'
|
31
31
|
|
32
32
|
require 'bosh/director/api/instance_lookup'
|
33
33
|
require 'bosh/director/api/deployment_lookup'
|
@@ -76,6 +76,33 @@ module Bosh::Director
|
|
76
76
|
rescue SystemCallError => e
|
77
77
|
raise SystemError, e.message
|
78
78
|
end
|
79
|
+
|
80
|
+
def prepare_yml_file(yml_stream, manifest_type, skip_validation = false)
|
81
|
+
random_file_name = "#{manifest_type}-#{SecureRandom.uuid}"
|
82
|
+
tmp_manifest_dir = Dir::tmpdir
|
83
|
+
|
84
|
+
manifest_file_path = File.join(tmp_manifest_dir, random_file_name)
|
85
|
+
unless check_available_disk_space(tmp_manifest_dir, yml_stream.size)
|
86
|
+
raise NotEnoughDiskSpace, 'Uploading manifest failed. ' +
|
87
|
+
"Insufficient space on BOSH director in #{tmp_manifest_dir}"
|
88
|
+
end
|
89
|
+
|
90
|
+
write_file(manifest_file_path, yml_stream)
|
91
|
+
|
92
|
+
validate_manifest_yml(File.read(manifest_file_path)) unless skip_validation
|
93
|
+
|
94
|
+
manifest_file_path
|
95
|
+
end
|
96
|
+
|
97
|
+
def validate_manifest_yml(yml_string)
|
98
|
+
raise BadManifest, 'Manifest should not be empty' unless yml_string.to_s != ''
|
99
|
+
|
100
|
+
begin
|
101
|
+
Psych.parse(yml_string)
|
102
|
+
rescue Psych::SyntaxError => e
|
103
|
+
raise BadManifest, "Incorrect YAML structure of the uploaded manifest: #{e.inspect}"
|
104
|
+
end
|
105
|
+
end
|
79
106
|
end
|
80
107
|
end
|
81
108
|
end
|
@@ -10,18 +10,14 @@ module Bosh::Director
|
|
10
10
|
@config = config
|
11
11
|
@logger = Config.logger
|
12
12
|
@identity_provider = config.identity_provider
|
13
|
-
@
|
13
|
+
@permission_authorizer = PermissionAuthorizer.new(config.get_uuid_provider)
|
14
14
|
@backup_manager = BackupManager.new
|
15
15
|
@restore_manager = RestoreManager.new
|
16
|
-
@instance_manager = InstanceManager.new
|
17
16
|
@resurrector_manager = ResurrectorManager.new
|
18
|
-
@problem_manager = ProblemManager.new(@deployment_manager)
|
19
|
-
@property_manager = PropertyManager.new(@deployment_manager)
|
20
17
|
@release_manager = ReleaseManager.new
|
21
18
|
@snapshot_manager = SnapshotManager.new
|
22
19
|
@stemcell_manager = StemcellManager.new
|
23
20
|
@task_manager = TaskManager.new
|
24
|
-
@vm_state_manager = VmStateManager.new
|
25
21
|
@dns_manager = DnsManagerProvider.create
|
26
22
|
@disk_manager = DiskManager.new(nil, @logger)
|
27
23
|
end
|
@@ -31,6 +27,8 @@ module Bosh::Director
|
|
31
27
|
mime_type :tgz, 'application/x-compressed'
|
32
28
|
mime_type :multipart, 'multipart/form-data'
|
33
29
|
|
30
|
+
ROUTES_WITH_EXTENDED_TIMEOUT = ['/stemcells', '/releases', '/restore']
|
31
|
+
|
34
32
|
attr_reader :identity_provider
|
35
33
|
|
36
34
|
def self.consumes(*types)
|
@@ -45,6 +43,31 @@ module Bosh::Director
|
|
45
43
|
end
|
46
44
|
end
|
47
45
|
|
46
|
+
before do
|
47
|
+
auth_provided = %w(HTTP_AUTHORIZATION X-HTTP_AUTHORIZATION X_HTTP_AUTHORIZATION).detect do |key|
|
48
|
+
request.env.has_key?(key)
|
49
|
+
end
|
50
|
+
|
51
|
+
if auth_provided
|
52
|
+
begin
|
53
|
+
extended_token_timeout = ROUTES_WITH_EXTENDED_TIMEOUT.include?(request.path) &&
|
54
|
+
request.media_type == mime_type(:multipart) &&
|
55
|
+
request.request_method == 'POST'
|
56
|
+
|
57
|
+
@user = identity_provider.get_user(request.env, extended_token_timeout: extended_token_timeout)
|
58
|
+
rescue AuthenticationError
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
if requires_authentication?
|
63
|
+
response['WWW-Authenticate'] = 'Basic realm="BOSH Director"'
|
64
|
+
if @user.nil?
|
65
|
+
message = "Not authorized: '#{request.path}'\n"
|
66
|
+
throw(:halt, [401, message])
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
48
71
|
def requires_authentication?
|
49
72
|
true
|
50
73
|
end
|
@@ -4,16 +4,17 @@ module Bosh::Director
|
|
4
4
|
module Api::Controllers
|
5
5
|
class CloudConfigsController < BaseController
|
6
6
|
post '/', :consumes => :yaml do
|
7
|
-
|
8
|
-
|
7
|
+
manifest_text = request.body.read
|
8
|
+
validate_manifest_yml(manifest_text)
|
9
9
|
|
10
|
+
Bosh::Director::Api::CloudConfigManager.new.update(manifest_text)
|
10
11
|
status(201)
|
11
12
|
end
|
12
13
|
|
13
14
|
get '/', scope: :read do
|
14
15
|
if params['limit'].nil? || params['limit'].empty?
|
15
16
|
status(400)
|
16
|
-
body(
|
17
|
+
body('limit is required')
|
17
18
|
return
|
18
19
|
end
|
19
20
|
|
@@ -2,17 +2,62 @@ require 'bosh/director/api/controllers/base_controller'
|
|
2
2
|
|
3
3
|
module Bosh::Director
|
4
4
|
module Api::Controllers
|
5
|
+
module DeploymentsSecurity
|
6
|
+
def route(verb, path, options = {}, &block)
|
7
|
+
options[:scope] ||= :authorization
|
8
|
+
options[:authorization] ||= :admin
|
9
|
+
super(verb, path, options, &block)
|
10
|
+
end
|
11
|
+
|
12
|
+
def authorization(perm)
|
13
|
+
return unless perm
|
14
|
+
|
15
|
+
condition do
|
16
|
+
subject = :director
|
17
|
+
permission = perm
|
18
|
+
|
19
|
+
if :diff == permission
|
20
|
+
begin
|
21
|
+
@deployment = Bosh::Director::Api::DeploymentLookup.new.by_name(params[:deployment])
|
22
|
+
subject = @deployment
|
23
|
+
permission = :admin
|
24
|
+
rescue DeploymentNotFound
|
25
|
+
permission = :create_deployment
|
26
|
+
end
|
27
|
+
else
|
28
|
+
if params.has_key?('deployment')
|
29
|
+
@deployment = Bosh::Director::Api::DeploymentLookup.new.by_name(params[:deployment])
|
30
|
+
subject = @deployment
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
@permission_authorizer.granted_or_raise(subject, permission, token_scopes)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
5
39
|
class DeploymentsController < BaseController
|
40
|
+
register DeploymentsSecurity
|
41
|
+
|
42
|
+
def initialize(config)
|
43
|
+
super(config)
|
44
|
+
@deployment_manager = Api::DeploymentManager.new
|
45
|
+
@problem_manager = Api::ProblemManager.new
|
46
|
+
@property_manager = Api::PropertyManager.new
|
47
|
+
@instance_manager = Api::InstanceManager.new
|
48
|
+
@deployments_repo = DeploymentPlan::DeploymentRepo.new
|
49
|
+
end
|
50
|
+
|
6
51
|
get '/:deployment/jobs/:job/:index_or_id' do
|
7
|
-
instance = @instance_manager.find_by_name(
|
52
|
+
instance = @instance_manager.find_by_name(deployment, params[:job], params[:index_or_id])
|
8
53
|
|
9
54
|
response = {
|
10
|
-
deployment:
|
55
|
+
deployment: deployment.name,
|
11
56
|
job: instance.job,
|
12
57
|
index: instance.index,
|
13
58
|
id: instance.uuid,
|
14
59
|
state: instance.state,
|
15
|
-
disks: instance.persistent_disks.map {|d| d.disk_cid}
|
60
|
+
disks: instance.persistent_disks.map { |d| d.disk_cid }
|
16
61
|
}
|
17
62
|
|
18
63
|
json_encode(response)
|
@@ -30,11 +75,15 @@ module Bosh::Director
|
|
30
75
|
}
|
31
76
|
options['skip_drain'] = params[:job] if params['skip_drain'] == 'true'
|
32
77
|
|
33
|
-
|
34
|
-
|
78
|
+
if (request.content_length.nil? || request.content_length.to_i == 0) && (params['state'])
|
79
|
+
manifest_file_path = prepare_yml_file(StringIO.new(deployment.manifest), 'deployment', true)
|
80
|
+
else
|
81
|
+
manifest_file_path = prepare_yml_file(request.body, 'deployment')
|
82
|
+
end
|
35
83
|
|
36
84
|
latest_cloud_config = Bosh::Director::Api::CloudConfigManager.new.latest
|
37
|
-
|
85
|
+
latest_runtime_config = Bosh::Director::Api::RuntimeConfigManager.new.latest
|
86
|
+
task = @deployment_manager.create_deployment(current_user, manifest_file_path, latest_cloud_config, latest_runtime_config, deployment.name, options)
|
38
87
|
redirect "/tasks/#{task.id}"
|
39
88
|
end
|
40
89
|
|
@@ -42,7 +91,7 @@ module Bosh::Director
|
|
42
91
|
put '/:deployment/jobs/:job/:index_or_id', :consumes => :yaml do
|
43
92
|
validate_instance_index_or_id(params[:index_or_id])
|
44
93
|
|
45
|
-
instance = @instance_manager.find_by_name(
|
94
|
+
instance = @instance_manager.find_by_name(deployment, params[:job], params[:index_or_id])
|
46
95
|
index = instance.index
|
47
96
|
|
48
97
|
options = {
|
@@ -56,16 +105,20 @@ module Bosh::Director
|
|
56
105
|
}
|
57
106
|
options['skip_drain'] = params[:job] if params['skip_drain'] == 'true'
|
58
107
|
|
59
|
-
|
60
|
-
|
108
|
+
if (request.content_length.nil? || request.content_length.to_i == 0)
|
109
|
+
manifest_file_path = prepare_yml_file(StringIO.new(deployment.manifest), 'deployment', true)
|
110
|
+
else
|
111
|
+
manifest_file_path = prepare_yml_file(request.body, 'deployment')
|
112
|
+
end
|
113
|
+
|
61
114
|
latest_cloud_config = Bosh::Director::Api::CloudConfigManager.new.latest
|
62
|
-
|
115
|
+
latest_runtime_config = Bosh::Director::Api::RuntimeConfigManager.new.latest
|
116
|
+
task = @deployment_manager.create_deployment(current_user, manifest_file_path, latest_cloud_config, latest_runtime_config, deployment.name, options)
|
63
117
|
redirect "/tasks/#{task.id}"
|
64
118
|
end
|
65
119
|
|
66
120
|
# GET /deployments/foo/jobs/dea/2/logs
|
67
121
|
get '/:deployment/jobs/:job/:index_or_id/logs' do
|
68
|
-
deployment = params[:deployment]
|
69
122
|
job = params[:job]
|
70
123
|
index_or_id = params[:index_or_id]
|
71
124
|
|
@@ -79,17 +132,14 @@ module Bosh::Director
|
|
79
132
|
end
|
80
133
|
|
81
134
|
get '/:deployment/snapshots' do
|
82
|
-
deployment = @deployment_manager.find_by_name(params[:deployment])
|
83
135
|
json_encode(@snapshot_manager.snapshots(deployment))
|
84
136
|
end
|
85
137
|
|
86
138
|
get '/:deployment/jobs/:job/:index/snapshots' do
|
87
|
-
deployment = @deployment_manager.find_by_name(params[:deployment])
|
88
139
|
json_encode(@snapshot_manager.snapshots(deployment, params[:job], params[:index]))
|
89
140
|
end
|
90
141
|
|
91
142
|
post '/:deployment/snapshots' do
|
92
|
-
deployment = @deployment_manager.find_by_name(params[:deployment])
|
93
143
|
# until we can tell the agent to flush and wait, all snapshots are considered dirty
|
94
144
|
options = {clean: false}
|
95
145
|
|
@@ -98,16 +148,16 @@ module Bosh::Director
|
|
98
148
|
end
|
99
149
|
|
100
150
|
put '/:deployment/jobs/:job/:index_or_id/resurrection', consumes: :json do
|
101
|
-
payload = json_decode(request.body)
|
102
151
|
|
103
|
-
|
152
|
+
payload = json_decode(request.body)
|
153
|
+
@resurrector_manager.set_pause_for_instance(deployment, params[:job], params[:index_or_id], payload['resurrection_paused'])
|
104
154
|
end
|
105
155
|
|
106
156
|
post '/:deployment/jobs/:job/:index_or_id/snapshots' do
|
107
157
|
if params[:index_or_id].to_s =~ /^\d+$/
|
108
|
-
instance = @instance_manager.find_by_name(
|
158
|
+
instance = @instance_manager.find_by_name(deployment, params[:job], params[:index_or_id])
|
109
159
|
else
|
110
|
-
instance = @instance_manager.filter_by(uuid: params[:index_or_id]).first
|
160
|
+
instance = @instance_manager.filter_by(deployment, uuid: params[:index_or_id]).first
|
111
161
|
end
|
112
162
|
# until we can tell the agent to flush and wait, all snapshots are considered dirty
|
113
163
|
options = {clean: false}
|
@@ -117,23 +167,22 @@ module Bosh::Director
|
|
117
167
|
end
|
118
168
|
|
119
169
|
delete '/:deployment/snapshots' do
|
120
|
-
deployment = @deployment_manager.find_by_name(params[:deployment])
|
121
|
-
|
122
170
|
task = @snapshot_manager.delete_deployment_snapshots_task(current_user, deployment)
|
123
171
|
redirect "/tasks/#{task.id}"
|
124
172
|
end
|
125
173
|
|
126
174
|
delete '/:deployment/snapshots/:cid' do
|
127
|
-
deployment = @deployment_manager.find_by_name(params[:deployment])
|
128
175
|
@snapshot_manager.find_by_cid(deployment, params[:cid])
|
129
176
|
|
130
177
|
task = @snapshot_manager.delete_snapshots_task(current_user, [params[:cid]])
|
131
178
|
redirect "/tasks/#{task.id}"
|
132
179
|
end
|
133
180
|
|
134
|
-
get '/',
|
181
|
+
get '/', authorization: :list_deployments do
|
135
182
|
latest_cloud_config = Api::CloudConfigManager.new.latest
|
136
|
-
deployments = @deployment_manager.
|
183
|
+
deployments = @deployment_manager.all_by_name_asc
|
184
|
+
.select { |deployment| @permission_authorizer.is_granted?(deployment, :read, token_scopes) }
|
185
|
+
.map do |deployment|
|
137
186
|
cloud_config = if deployment.cloud_config.nil?
|
138
187
|
'none'
|
139
188
|
elsif deployment.cloud_config == latest_cloud_config
|
@@ -163,26 +212,33 @@ module Bosh::Director
|
|
163
212
|
json_encode(deployments)
|
164
213
|
end
|
165
214
|
|
166
|
-
get '/:
|
167
|
-
|
168
|
-
@deployment_manager.deployment_to_json(deployment)
|
215
|
+
get '/:deployment', authorization: :read do
|
216
|
+
Yajl::Encoder.encode({'manifest' => deployment.manifest})
|
169
217
|
end
|
170
218
|
|
171
|
-
get '/:
|
172
|
-
deployment = @deployment_manager.find_by_name(params[:name])
|
173
|
-
|
219
|
+
get '/:deployment/vms', authorization: :read do
|
174
220
|
format = params[:format]
|
175
221
|
if format == 'full'
|
176
|
-
task = @
|
222
|
+
task = @instance_manager.fetch_instances_with_vm(current_user, deployment, format)
|
177
223
|
redirect "/tasks/#{task.id}"
|
178
224
|
else
|
179
|
-
@deployment_manager.
|
225
|
+
instances = @deployment_manager.deployment_instances_with_vms(deployment)
|
226
|
+
Yajl::Encoder.encode(create_instances_response(instances))
|
180
227
|
end
|
181
228
|
end
|
182
229
|
|
183
|
-
|
184
|
-
|
230
|
+
get '/:deployment/instances', authorization: :read do
|
231
|
+
format = params[:format]
|
232
|
+
if format == 'full'
|
233
|
+
task = @instance_manager.fetch_instances(current_user, deployment, format)
|
234
|
+
redirect "/tasks/#{task.id}"
|
235
|
+
else
|
236
|
+
instances = @instance_manager.find_instances_by_deployment(deployment)
|
237
|
+
Yajl::Encoder.encode(create_instances_response(instances))
|
238
|
+
end
|
239
|
+
end
|
185
240
|
|
241
|
+
delete '/:deployment' do
|
186
242
|
options = {}
|
187
243
|
options['force'] = true if params['force'] == 'true'
|
188
244
|
options['keep_snapshots'] = true if params['keep_snapshots'] == 'true'
|
@@ -190,39 +246,39 @@ module Bosh::Director
|
|
190
246
|
redirect "/tasks/#{task.id}"
|
191
247
|
end
|
192
248
|
|
249
|
+
post '/:deployment/ssh', :consumes => [:json] do
|
250
|
+
payload = json_decode(request.body)
|
251
|
+
task = @instance_manager.ssh(current_user, deployment, payload)
|
252
|
+
redirect "/tasks/#{task.id}"
|
253
|
+
end
|
254
|
+
|
193
255
|
# Property management
|
194
256
|
get '/:deployment/properties' do
|
195
|
-
properties = @property_manager.get_properties(
|
196
|
-
{
|
257
|
+
properties = @property_manager.get_properties(deployment).map do |property|
|
258
|
+
{'name' => property.name, 'value' => property.value}
|
197
259
|
end
|
198
260
|
json_encode(properties)
|
199
261
|
end
|
200
262
|
|
201
263
|
get '/:deployment/properties/:property' do
|
202
|
-
property = @property_manager.get_property(
|
264
|
+
property = @property_manager.get_property(deployment, params[:property])
|
203
265
|
json_encode('value' => property.value)
|
204
266
|
end
|
205
267
|
|
206
268
|
post '/:deployment/properties', :consumes => [:json] do
|
207
269
|
payload = json_decode(request.body)
|
208
|
-
@property_manager.create_property(
|
270
|
+
@property_manager.create_property(deployment, payload['name'], payload['value'])
|
209
271
|
status(204)
|
210
272
|
end
|
211
273
|
|
212
|
-
post '/:deployment/ssh', :consumes => [:json] do
|
213
|
-
payload = json_decode(request.body)
|
214
|
-
task = @instance_manager.ssh(current_user, payload)
|
215
|
-
redirect "/tasks/#{task.id}"
|
216
|
-
end
|
217
|
-
|
218
274
|
put '/:deployment/properties/:property', :consumes => [:json] do
|
219
275
|
payload = json_decode(request.body)
|
220
|
-
@property_manager.update_property(
|
276
|
+
@property_manager.update_property(deployment, params[:property], payload['value'])
|
221
277
|
status(204)
|
222
278
|
end
|
223
279
|
|
224
280
|
delete '/:deployment/properties/:property' do
|
225
|
-
@property_manager.delete_property(
|
281
|
+
@property_manager.delete_property(deployment, params[:property])
|
226
282
|
status(204)
|
227
283
|
end
|
228
284
|
|
@@ -230,12 +286,12 @@ module Bosh::Director
|
|
230
286
|
|
231
287
|
# Initiate deployment scan
|
232
288
|
post '/:deployment/scans' do
|
233
|
-
start_task { @problem_manager.perform_scan(current_user,
|
289
|
+
start_task { @problem_manager.perform_scan(current_user, deployment) }
|
234
290
|
end
|
235
291
|
|
236
292
|
# Get the list of problems for a particular deployment
|
237
293
|
get '/:deployment/problems' do
|
238
|
-
problems = @problem_manager.get_problems(
|
294
|
+
problems = @problem_manager.get_problems(deployment).map do |problem|
|
239
295
|
{
|
240
296
|
'id' => problem.id,
|
241
297
|
'type' => problem.type,
|
@@ -250,84 +306,104 @@ module Bosh::Director
|
|
250
306
|
|
251
307
|
put '/:deployment/problems', :consumes => [:json] do
|
252
308
|
payload = json_decode(request.body)
|
253
|
-
start_task { @problem_manager.apply_resolutions(current_user,
|
309
|
+
start_task { @problem_manager.apply_resolutions(current_user, deployment, payload['resolutions']) }
|
254
310
|
end
|
255
311
|
|
256
312
|
put '/:deployment/scan_and_fix', :consumes => :json do
|
257
313
|
jobs_json = json_decode(request.body)['jobs']
|
258
314
|
payload = convert_job_instance_hash(jobs_json)
|
259
|
-
|
260
|
-
deployment = @deployment_manager.find_by_name(params[:deployment])
|
261
315
|
if deployment_has_instance_to_resurrect?(deployment)
|
262
|
-
start_task { @problem_manager.scan_and_fix(current_user,
|
316
|
+
start_task { @problem_manager.scan_and_fix(current_user, deployment, payload) }
|
263
317
|
end
|
264
318
|
end
|
265
319
|
|
266
|
-
post '/', :consumes => :yaml do
|
320
|
+
post '/', authorization: :create_deployment, :consumes => :yaml do
|
321
|
+
manifest_file_path = prepare_yml_file(request.body, 'deployment')
|
322
|
+
|
267
323
|
options = {}
|
268
324
|
options['recreate'] = true if params['recreate'] == 'true'
|
269
325
|
options['skip_drain'] = params['skip_drain'] if params['skip_drain']
|
326
|
+
options.merge!('scopes' => token_scopes)
|
327
|
+
|
270
328
|
if params['context']
|
271
329
|
@logger.debug("Deploying with context #{params['context']}")
|
272
330
|
context = JSON.parse(params['context'])
|
273
331
|
cloud_config = Api::CloudConfigManager.new.find_by_id(context['cloud_config_id'])
|
332
|
+
runtime_config = Api::RuntimeConfigManager.new.find_by_id(context['runtime_config_id'])
|
274
333
|
else
|
275
334
|
cloud_config = Api::CloudConfigManager.new.latest
|
335
|
+
runtime_config = Api::RuntimeConfigManager.new.latest
|
276
336
|
end
|
277
337
|
|
278
|
-
|
279
|
-
|
338
|
+
deployment = Psych.load(File.read(manifest_file_path), manifest_file_path)
|
339
|
+
|
340
|
+
if deployment
|
341
|
+
deployment_name = deployment['name']
|
342
|
+
if deployment_name
|
343
|
+
@deployments_repo.find_or_create_by_name(deployment_name, options)
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
task = @deployment_manager.create_deployment(current_user, manifest_file_path, cloud_config, runtime_config, deployment_name, options)
|
348
|
+
|
280
349
|
redirect "/tasks/#{task.id}"
|
281
350
|
end
|
282
351
|
|
283
|
-
post '/:deployment/diff', :consumes => :yaml do
|
284
|
-
|
352
|
+
post '/:deployment/diff', authorization: :diff, :consumes => :yaml do
|
353
|
+
manifest_text = request.body.read
|
354
|
+
validate_manifest_yml(manifest_text)
|
355
|
+
|
285
356
|
if deployment
|
286
|
-
before_manifest = Manifest.load_from_text(deployment.manifest, deployment.cloud_config)
|
357
|
+
before_manifest = Manifest.load_from_text(deployment.manifest, deployment.cloud_config, deployment.runtime_config)
|
287
358
|
before_manifest.resolve_aliases
|
288
359
|
else
|
289
|
-
before_manifest = Manifest.load_from_text(nil, nil)
|
360
|
+
before_manifest = Manifest.load_from_text(nil, nil, nil)
|
290
361
|
end
|
291
362
|
|
292
363
|
after_cloud_config = Bosh::Director::Api::CloudConfigManager.new.latest
|
364
|
+
after_runtime_config = Bosh::Director::Api::RuntimeConfigManager.new.latest
|
293
365
|
after_manifest = Manifest.load_from_text(
|
294
|
-
|
295
|
-
after_cloud_config
|
366
|
+
manifest_text,
|
367
|
+
after_cloud_config,
|
368
|
+
after_runtime_config
|
296
369
|
)
|
297
370
|
after_manifest.resolve_aliases
|
298
371
|
|
299
|
-
|
372
|
+
redact = params['redact'] != 'false'
|
373
|
+
|
374
|
+
diff = before_manifest.diff(after_manifest, redact)
|
300
375
|
|
301
376
|
json_encode({
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
377
|
+
'context' => {
|
378
|
+
'cloud_config_id' => after_cloud_config ? after_cloud_config.id : nil,
|
379
|
+
'runtime_config_id' => after_runtime_config ? after_runtime_config.id : nil
|
380
|
+
},
|
381
|
+
'diff' => diff.map { |l| [l.to_s, l.status] }
|
382
|
+
})
|
307
383
|
end
|
308
384
|
|
309
|
-
post '/:
|
310
|
-
deployment_name = params[:deployment_name]
|
385
|
+
post '/:deployment/errands/:errand_name/runs' do
|
311
386
|
errand_name = params[:errand_name]
|
312
387
|
keep_alive = json_decode(request.body)['keep-alive'] || FALSE
|
313
388
|
|
314
389
|
task = JobQueue.new.enqueue(
|
315
390
|
current_user,
|
316
391
|
Jobs::RunErrand,
|
317
|
-
"run errand #{errand_name} from deployment #{
|
318
|
-
[
|
392
|
+
"run errand #{errand_name} from deployment #{deployment.name}",
|
393
|
+
[deployment.name, errand_name, keep_alive],
|
394
|
+
deployment.name
|
319
395
|
)
|
320
396
|
|
321
397
|
redirect "/tasks/#{task.id}"
|
322
398
|
end
|
323
399
|
|
324
|
-
get '/:
|
400
|
+
get '/:deployment/errands', authorization: :read do
|
325
401
|
deployment_plan = load_deployment_plan
|
326
402
|
|
327
|
-
errands = deployment_plan.jobs.select(&:
|
403
|
+
errands = deployment_plan.jobs.select(&:is_errand?)
|
328
404
|
|
329
405
|
errand_data = errands.map do |errand|
|
330
|
-
{
|
406
|
+
{"name" => errand.name}
|
331
407
|
end
|
332
408
|
|
333
409
|
json_encode(errand_data)
|
@@ -335,11 +411,11 @@ module Bosh::Director
|
|
335
411
|
|
336
412
|
private
|
337
413
|
|
338
|
-
|
339
|
-
deployment_model = @deployment_manager.find_by_name(params[:deployment_name])
|
414
|
+
attr_accessor :deployment
|
340
415
|
|
416
|
+
def load_deployment_plan
|
341
417
|
planner_factory = Bosh::Director::DeploymentPlan::PlannerFactory.create(Config.logger)
|
342
|
-
planner_factory.create_from_model(
|
418
|
+
planner_factory.create_from_model(deployment)
|
343
419
|
end
|
344
420
|
|
345
421
|
def convert_job_instance_hash(hash)
|
@@ -351,11 +427,7 @@ module Bosh::Director
|
|
351
427
|
|
352
428
|
def deployment_has_instance_to_resurrect?(deployment)
|
353
429
|
false if deployment.nil?
|
354
|
-
|
355
|
-
deployment_id: deployment.id,
|
356
|
-
resurrection_paused: false
|
357
|
-
}
|
358
|
-
instances = @instance_manager.filter_by(filter)
|
430
|
+
instances = @instance_manager.filter_by(deployment, resurrection_paused: false)
|
359
431
|
instances.any?
|
360
432
|
end
|
361
433
|
|
@@ -368,6 +440,18 @@ module Bosh::Director
|
|
368
440
|
end
|
369
441
|
end
|
370
442
|
end
|
443
|
+
|
444
|
+
def create_instances_response(instances)
|
445
|
+
instances.map do |instance|
|
446
|
+
{
|
447
|
+
'agent_id' => instance.agent_id,
|
448
|
+
'cid' => instance.vm_cid,
|
449
|
+
'job' => instance.job,
|
450
|
+
'index' => instance.index,
|
451
|
+
'id' => instance.uuid
|
452
|
+
}
|
453
|
+
end
|
454
|
+
end
|
371
455
|
end
|
372
456
|
end
|
373
457
|
end
|