Ravn::Tactical::

BoltPackage class

A wrapper of convenience functions for reading and writing the Ravn Bolt package on a compute pack.

Constants

DEFAULT_NAME

The name of the default bolt package that is used if none has been uploaded yet.

FILENAME

The name of the file the bolts package is contained in, relative to the configured mission directory.

MAX_PACKAGE_VERSION

The maximum version number of the package format that is supported.

TIMESTAMP_FORMAT

Strtime format for the timestamp field

Attributes

bolts R

The bolt library’s bolts

name R

The bolt library’s human-readable name

roles R

The bolt library’s roles as a Set of Ravn::Tactical::Roles

timestamp R

The timestamp when the bolt library was exported from the Creator

Public Class Methods

default_path()

Return a Pathname to the default file containing the BoltPackage data.

   # File lib/ravn/tactical/bolt_package.rb
43 def self::default_path
44     return Ravn::BDE.mission_directory + FILENAME
45 end
exists?()

Returns true if the bolts package file exists in the currently-configured mission directory.

    # File lib/ravn/tactical/bolt_package.rb
114 def self::exists?
115     return self.default_path.exist?
116 end
load( path=self.default_path )

Load the BoltPackage from the specified path and return it.

   # File lib/ravn/tactical/bolt_package.rb
49 def self::load( path=self.default_path )
50     path = Pathname( path )
51     raw = YAML.safe_load_file( path, symbolize_names: true ) or
52         raise "Failed to load %s" % [ path ]
53 
54     fields = self.normalize_fields( raw )
55 
56     return new( **fields )
57 end
new( name: DEFAULT_NAME, roles: [], bolts: {}, timestamp: Time.now )

Create a new BoltPackage with the given name,

    # File lib/ravn/tactical/bolt_package.rb
120 def initialize( name: DEFAULT_NAME, roles: [], bolts: {}, timestamp: Time.now )
121     @name      = name
122     @roles     = roles.map {|name| Ravn::Tactical::Role.new(name) }.to_set
123     @timestamp = timestamp
124 
125     @bolts = bolts.each_with_object( {} ) do |(id, bolt), acc|
126         bolt      = bolt.is_a?( Ravn::Tactical::Bolt ) ? bolt : Ravn::Tactical::Bolt.new( **bolt )
127         bolt.id   = id
128         acc[ id ] = bolt
129     end
130 end
new_with_defaults()

Return an unsaved BoltPackage derived from the default mission templates.

    # File lib/ravn/tactical/bolt_package.rb
 96 def self::new_with_defaults
 97     segments = Set.new
 98     bolts = {}
 99 
100     Ravn::Tactical::Mission.all_templates.each do |template|
101         segments.merge( template.segments.keys.map(&:to_s) )
102         bolts.merge!( template.bolts )
103     end
104 
105     return new(
106         roles: segments,
107         bolts: bolts
108     )
109 end
normalize_fields( raw )

Normalize the fields in the raw bolt package data according to the version of the format it’s in and return the normalized Hash. Raises a Ravn::Tactical::BoltPackageError if raw contains invalid or unsupported values.

   # File lib/ravn/tactical/bolt_package.rb
64 def self::normalize_fields( raw )
65     package_version = raw.delete( :package_version ) or
66         raise Ravn::Tactical::BoltPackageError, "No package_version!"
67     self.log.debug "Raw data is format version %d" % [ package_version ]
68 
69     normalized = {}
70     case package_version
71     when 1
72         normalized[ :name ] = raw[ :library ]
73         normalized[ :roles ] = raw[ :segments ]
74         normalized[ :bolts ] = raw[ :bolts ].transform_keys( &:to_s )
75         # :TODO: Change to epoch integer/float so we have zone?
76         normalized[ :timestamp ] = Time.strptime( raw[:timestamp], TIMESTAMP_FORMAT )
77     else
78         raise Ravn::Tactical::BoltPackageError,
79             "unsupported package version %d" % [ package_version ]
80     end
81 
82     return normalized
83 end
write_default( path=self.default_path )

Write a default set of bolts to the Bolt Package file. Raises an exception if the file already exists.

   # File lib/ravn/tactical/bolt_package.rb
88 def self::write_default( path=self.default_path )
89     package = self.new_with_defaults
90     package.write_as_default
91     return package
92 end

Public Instance Methods

==( other_object )

Return true if other_object is the same BoltPackage as the receiver.

    # File lib/ravn/tactical/bolt_package.rb
221 def ==( other_object )
222     return other_object.is_a?( self.class ) &&
223         other_object.fields == self.fields
224 end
fields()

Return a Hash of normalized values for the BoltPackage suitable for writing to a file or to the network.

    # File lib/ravn/tactical/bolt_package.rb
164 def fields
165     return {
166         package_version: MAX_PACKAGE_VERSION,
167         library: self.name,
168         timestamp: self.timestamp.strftime( TIMESTAMP_FORMAT ),
169         segments: self.roles.map( &:name ).sort,
170         bolts: self.bolts.transform_values( &:fields ),
171     }
172 end
inspect_details()

Ravn::Inspection API – return the details of the BoltPackage in human-readable form.

    # File lib/ravn/tactical/bolt_package.rb
229 def inspect_details
230     return "%s [%s]: %d roles, %d bolts" % [
231         self.name,
232         self.timestamp,
233         self.roles.size,
234         self.bolts.size,
235     ]
236 end
role_segments_hash()

Return the bolt package’s role as a Hash of Segments keyed by role name.

    # File lib/ravn/tactical/bolt_package.rb
155 def role_segments_hash
156     return self.roles.each_with_object({}) do |role, hash|
157         hash[ role.name ] = { type: 'group', config: { members: [] } }
158     end
159 end
validate()

Check the contents of the BoltPackage for validity, raising a Ravn::Tactical::BoltPackageError if there’s a problem.

    # File lib/ravn/tactical/bolt_package.rb
177 def validate
178     self.validate_bolts
179 end
validate_bolts()

Validate the BoltPackage’s bolts, raising a Ravn::Tactical::BoltPackageError if one of them is not valid.

    # File lib/ravn/tactical/bolt_package.rb
184 def validate_bolts
185     self.bolts.each do |bolt_id, bolt|
186         self.log.debug "Validating bolt %s: %p" % [ bolt_id, bolt ]
187         raise Ravn::Tactical::BoltPackageError, "invalid bolt %s" % [ bolt_id ] unless
188             bolt.valid?
189     end
190 end
write( path, replace: false )

Write the BoltPackage to the given path.

    # File lib/ravn/tactical/bolt_package.rb
194 def write( path, replace: false )
195     path = Pathname( path )
196     path.unlink if replace && path.exist?
197 
198     raise "Directory %s doesn not exist!" % [ path.dirname ] if !path.dirname.directory?
199 
200     io = path.open( File::WRONLY|File::CREAT|File::EXCL, 0644 )
201     package = stringify_keys( self.fields )
202 
203     self.log.warn "Writing a bolt package to %s" % [ path ]
204     YAML.safe_dump( package, io )
205 
206     io.close
207     self.log.debug "Written file is %d bytes" % [ path.size ]
208 end
write_as_default( replace: false )

Write the BoltPackage to the default path, overwriting an existing one if the replace option is set.

    # File lib/ravn/tactical/bolt_package.rb
213 def write_as_default( replace: false )
214     self.log.info "Writing package with timestamp %s as the default" % [ self.timestamp ]
215     path = self.class.default_path
216     self.write( path, replace: )
217 end