Class: Blufin::Projects

Inherits:
Object
  • Object
show all
Defined in:
lib/core/projects.rb

Constant Summary collapse

SCHEMA_FILE =
"#{Blufin::Base::get_base_path}#{Blufin::Base::OPT_PATH}/schema/projects.yml"
SCHEMA_FILE_CODEGEN =
"#{Blufin::Base::get_base_path}#{Blufin::Base::OPT_PATH}/schema/codegen.yml"
SCRIPT_RUN =
'run'
SCRIPT_TEST =
'test'
SCRIPT_BUILD =
'build'
SCRIPT_DEPLOY =
'deploy'
RUN_SCRIPTS =
'RunScripts'
TEST_SCRIPTS =
'TestScripts'
BUILD_SCRIPTS =
'BuildScripts'
ID =
'Id'
PROJECT_ID =
'ProjectId'
PROJECT =
'Project'
PROJECT_ROOT =
'ProjectRoot'
TYPE =
'Type'
REPOSITORY =
'Repository'
UPSTREAM =
'Upstream'
DOWNSTREAM =
'Downstream'
LOCAL =
'Local'
REMOTE =
'Remote'
FILE =
'File'
DEPLOYMENT =
'Deployment'
DEPLOYMENT_BUCKET =
'Bucket'
DEPLOYMENT_FILES =
'Files'
RUN =
'Run'
TEST =
'Test'
BUILD =
'Build'
COMMANDS =
'Commands'
API =
'API'
SCHEDULER =
'Scheduler'
WORKER =
'Worker'
LAMBDA =
'Lambda'
UI =

TODO - Probably need to extend this to every type of UI.

'UI'
TRANSIENT_DATA =
'TransientData'
CODEGEN =
'codegen'
CG_API_SIMPLE =
'ApiSimple'
CG_QUASAR =
'Quasar'
CG_QUASAR_ROOT =
'Root'
CG_QUASAR_PAGES =
'PathPages'
CG_QUASAR_PAGES_IGNORE =
'PathPagesIgnore'
CG_QUASAR_API_DOCS_FILE =
'ApiDocsFile'
CG_QUASAR_JS =
'JsPath'
CG_QUASAR_TESTS =
'JsPathTests'
CG_QUASAR_ROUTES_FILE =
'RoutesFile'
TITLE =
'Title'
ALIAS =
'Alias'
DOMAIN =
'Domain'
PROJECT_NAME_PASCAL_CASE =
'ProjectNamePascalCase'
PROJECT_NAME =
'ProjectName'
PORT =
'Port'
PORTS =
'Ports'
STAGES =
'Stages'
TYPE_ALEXA =
'alexa'
TYPE_API =
'api'
TYPE_API_SIMPLE =
'api-simple'
TYPE_LAMBDA =
'lambda'
TYPE_MVN_LIB =
'mvn-lib'
TYPE_NPM_LIB =
'npm-lib'
TYPE_MOBILE =
'mobile'
TYPE_QUASAR =
'quasar'
TYPE_UI =

TODO - Probably need to extend this to every type of UI.

'ui'
VALID_TYPES =
[
    TYPE_ALEXA,
    TYPE_API,
    TYPE_API_SIMPLE,
    TYPE_LAMBDA,
    TYPE_MVN_LIB,
    TYPE_NPM_LIB,
    TYPE_QUASAR,
    TYPE_UI,
    TYPE_MOBILE,
]
@@projects =
nil
@@projects_arr =
[]
@@projects_cache =
{}
@@project_names =
[]
@@project_ids =
[]
@@scripts =
nil
@@apis =
nil
@@api_data =
{}
@@lambdas =
nil
@@libs =
{}
@@dependant_projects_cache =
{}
@@dependant_repos_cache =
{}
@@project_path_cache =
{}

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(projects, profile = nil) ⇒ Object

Takes a Hash that needs to have a ‘Projects’ key. This can come from both .awx.yml or .blufin.yml (root).

Raises:

  • (RuntimeError)


94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/core/projects.rb', line 94

def initialize(projects, profile = nil)
    raise RuntimeError, 'Cannot run Blufin::Projects.new() more than once.' if !@@projects.nil? || !@@scripts.nil?
    raise RuntimeError, "Need either a Local or S3Bucket key, found neither: #{projects.keys}" unless projects.has_key?(LOCAL) || projects.has_key?('S3Bucket')
    @@projects = {}
    @@scripts  = {}
    if projects.has_key?(LOCAL)
        source_file = File.expand_path(projects[LOCAL][FILE])
        # Throw error if source file doesn't exist.
        Blufin::Terminal::error("Cannot find source file: #{Blufin::Terminal::format_directory(source_file)}") unless Blufin::Files::file_exists(source_file)
        # Validate the source file against the expected schema.
        process_source_file(source_file)
    elsif projects.has_key?('S3Bucket')
        # Throw an error if we don't have an AWS Profile.
        Blufin::Terminal::error("Your configuration is getting #{Blufin::Terminal::format_highlight('projects.yml')} from S3, but you have no AWS Profile set.") if profile.nil?
        s3       = projects['S3Bucket']
        tmp_path = Blufin::AWS::download_s3_data(s3['Name'], s3['Path'], file: s3['File'], profile: profile, region: s3['Region'], use_cache: true)
        process_source_file(tmp_path)
    end
end

Class Method Details

.get_apisObject

Gets API(s).

Returns:

  • Hash



156
157
158
# File 'lib/core/projects.rb', line 156

def self.get_apis
    @@apis
end

.get_dependant_projects(project_id, streams: [UPSTREAM, DOWNSTREAM], processed_projects: []) ⇒ Object

Gets a hash of dependant projects (with the Project IDs as keys). processed_projects Array prevents cyclic-dependency stack overflow.

Returns:

  • Hash

Raises:

  • (RuntimeError)


236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/core/projects.rb', line 236

def self.get_dependant_projects(project_id, streams: [UPSTREAM, DOWNSTREAM], processed_projects: [])
    valid_streams = [UPSTREAM, DOWNSTREAM]
    raise RuntimeError, "Expected Array, instead got: #{streams.class}" unless streams.is_a?(Array)
    streams.each { |s| raise RuntimeError, "Invalid stream: #{s}" unless valid_streams.include?(s) }
    key = "#{project_id}-#{streams.join('-')}"
    return @@dependant_projects_cache[key] if @@dependant_projects_cache.has_key?(key)
    dependant_projects = {}
    project            = get_project_by_id(project_id, true)
    streams.each do |stream|
        if project.has_key?(stream)
            project[stream].each do |dependant_project_id|
                unless processed_projects.include?(dependant_project_id)
                    processed_projects << dependant_project_id
                    dependant_projects[dependant_project_id] = get_project_by_id(dependant_project_id, true) unless dependant_projects.has_key?(dependant_project_id)
                    dependant_projects_inner                 = Blufin::Projects::get_dependant_projects(dependant_project_id, streams: streams, processed_projects: processed_projects)
                    # Add nested dependant projects (if any).
                    dependant_projects_inner.each { |k, v| dependant_projects[k] = v unless dependant_projects.has_key?(k) } if dependant_projects_inner.any?
                end
            end
        end
    end
    # Don't include project itself in dependant projects.
    dependant_projects.delete(project_id) if dependant_projects.has_key?(project_id)
    @@dependant_projects_cache[key] = dependant_projects
    @@dependant_projects_cache[key]
end

.get_dependant_repos(project_id, streams: [UPSTREAM, DOWNSTREAM]) ⇒ Object

Same as above, but only gets the repositories. Sometimes multiple dependant_project IDs may have the same repository.

Returns:

  • Hash



266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# File 'lib/core/projects.rb', line 266

def self.get_dependant_repos(project_id, streams: [UPSTREAM, DOWNSTREAM])
    key = "#{project_id}-#{streams.join('-')}"
    return @@dependant_repos_cache[key] if @@dependant_repos_cache.has_key?(key)
    dependant_repos = {}
    get_dependant_projects(project_id, streams: streams).each do |k, v|
        next if k == project_id
        repo                         = v[REPOSITORY][REMOTE]
        dependant_repos[repo]        = {
            :projects => []
        } unless dependant_repos.include?(repo)
        dependant_repos[repo][:path] = v[REPOSITORY][LOCAL] if v[REPOSITORY].has_key?(LOCAL)
        dependant_repos[repo][:projects] << k unless dependant_repos[repo][:projects].include?(k)
    end
    @@dependant_repos_cache[key] = dependant_repos
    @@dependant_repos_cache[key]
end

.get_lambdasObject

Gets Lambda(s).

Returns:

  • Hash



162
163
164
# File 'lib/core/projects.rb', line 162

def self.get_lambdas
    @@lambdas
end

.get_project_by_id(project_id, runtime_error = false) ⇒ Object

Attempts to get a project’s data by ID, displays error if not exists.

Returns:

  • string

Raises:

  • (RuntimeError)


168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/core/projects.rb', line 168

def self.get_project_by_id(project_id, runtime_error = false)
    raise RuntimeError, "Expected String, instead got: #{project_id.class}" unless project_id.is_a?(String)
    return @@projects_cache[project_id] if @@projects_cache.has_key?(project_id)
    project_data = nil
    if @@projects_arr.is_a?(Array)
        @@projects_arr.each do |project|
            raise RuntimeError, 'Missing Project ID.' unless project.has_key?(PROJECT_ID)
            if project[PROJECT_ID].strip.downcase == project_id.strip.downcase
                project_data = project
                break
            end
        end
    end
    raise RuntimeError, "Unrecognized Project ID: #{project_id}" if project_data.nil? && runtime_error
    Blufin::Terminal::error("Unrecognized Project ID: #{Blufin::Terminal::format_invalid(project_id)} . Available Projects IDs are:", get_project_ids) if project_data.nil? && !runtime_error
    @@projects_cache[project_id] = project_data
    @@projects_cache[project_id]
end

.get_project_idsObject

Gets Project ID(s).

Returns:

  • Array



144
145
146
# File 'lib/core/projects.rb', line 144

def self.get_project_ids
    @@project_ids
end

.get_project_namesObject

Gets Project Name(s).

Returns:

  • Array



138
139
140
# File 'lib/core/projects.rb', line 138

def self.get_project_names
    @@project_names
end

.get_project_path(project_id, to_inner_project = false, is_ec2: false, project: nil) ⇒ Object

Gets the path to a project. By default, gets the root (IE: doesn’t take into account ‘Repository.ProjectRoot’ key). If you want the full path to the inner project, to_inner_project must be set to TRUE. If local, simply returns path in projects.yml. If not local (IE: on EC2), returns a standardized /tmp path.

Returns:

  • string

Raises:

  • (RuntimeError)


211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/core/projects.rb', line 211

def self.get_project_path(project_id, to_inner_project = false, is_ec2: false, project: nil)
    key = "#{project_id}|#{to_inner_project}|#{is_ec2}"
    return @@project_path_cache[key] if @@project_path_cache.has_key?(key)
    project      = project.nil? ? get_project_by_id(project_id, true) : project
    repo_data    = project[REPOSITORY]
    inner_path   = repo_data.has_key?(PROJECT_ROOT) ? Blufin::Strings::remove_surrounding_slashes(repo_data[PROJECT_ROOT]) : ''
    project_path = nil
    if repo_data.has_key?(LOCAL) && !is_ec2
        root_path    = Blufin::Strings::remove_surrounding_slashes(File.expand_path(repo_data[LOCAL]))
        project_path = "/#{root_path}" unless to_inner_project
        project_path = "/#{root_path}#{inner_path.length > 0 ? '/' : ''}#{inner_path}" if to_inner_project
    else
        rs           = repo_data[REMOTE].split('/')
        tmp_path     = "/tmp/repo-#{rs[rs.length - 1].gsub(/\.git$/i, '')}"
        project_path = tmp_path unless to_inner_project
        project_path = "#{tmp_path}#{inner_path.length > 0 ? '/' : ''}#{inner_path}" if to_inner_project
    end
    raise RuntimeError, "Project Path should never be nil or an empty string: #{key}" if project_path.nil? || project_path.strip == ''
    @@project_path_cache[key] = project_path
    @@project_path_cache[key]
end

.get_project_repo_name(project_id) ⇒ Object

Gets repo-name from project_id.

Returns:

  • string



285
286
287
288
# File 'lib/core/projects.rb', line 285

def self.get_project_repo_name(project_id)
    project = get_project_by_id(project_id, true)
    Blufin::Git::extract_repo_name(project[REPOSITORY][REMOTE])
end

.get_projectsObject

Gets Project(s) – as a nested hash with -> [PROJECT] as the keys.

Returns:

  • Hash



116
117
118
# File 'lib/core/projects.rb', line 116

def self.get_projects
    @@projects
end

.get_projects_as_array(group: nil, types: nil) ⇒ Object

Gets Project(s) – but in a single array.

Returns:

  • Array



122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/core/projects.rb', line 122

def self.get_projects_as_array(group: nil, types: nil)
    projects_arr = []
    unless types.nil?
        types = [types] unless types.is_a?(Array)
        types.each { |type| raise RuntimeError, "Invalid type: #{type}" unless VALID_TYPES.include?(type) }
    end
    @@projects_arr.each do |project|
        next if !group.nil? && group != project[PROJECT]
        next if !types.nil? && !types.include?(project[TYPE])
        projects_arr << project
    end
    projects_arr
end

.get_projects_by_pathObject

Gets an array of project(s) from current path.

Returns:

  • Array



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/core/projects.rb', line 189

def self.get_projects_by_path
    projects     = {}
    current_path = Blufin::Strings::strip_newline(`pwd`)
    get_projects_as_array.each do |project|
        if project.has_key?(REPOSITORY)
            if project[REPOSITORY].has_key?(LOCAL)
                project_path = File.expand_path(project[REPOSITORY][LOCAL])
                if current_path =~ /^#{project_path}/
                    raise RuntimeError, 'Missing Project ID.' unless project.has_key?(PROJECT_ID)
                    projects[project[PROJECT_ID]] = project
                end
            end
        end
    end
    projects
end

.get_scriptsObject

Gets Script(s).

Returns:

  • Hash



150
151
152
# File 'lib/core/projects.rb', line 150

def self.get_scripts
    @@scripts
end

.show_project_prompt(array_of_projects) ⇒ Object

Shows a prompt and returns project Hash once selected. If only one project exists, prompt not displayed.

Returns:

  • Hash

Raises:

  • (RuntimeError)


293
294
295
296
297
298
299
300
# File 'lib/core/projects.rb', line 293

def self.show_project_prompt(array_of_projects)
    raise RuntimeError, "Expected Array, instead got: #{array_of_projects.class}" unless array_of_projects.is_a?(Array)
    Blufin::Terminal::error('No projects found.') unless array_of_projects.any?
    return array_of_projects[0] if array_of_projects.length == 1
    projects = []
    array_of_projects.each { |project| projects << { :text => project[PROJECT_ID], :value => project } }
    Blufin::Terminal::prompt_select('Select project:', projects)
end