Module: Y2Firewall::Firewalld::Relations

Included in:
Y2Firewall::Firewalld, Service, Zone
Defined in:
library/network/src/lib/y2firewall/firewalld/relations.rb

Overview

Extends the base class with metaprogramming methods which defines some attributes common logic.

Instance Method Summary collapse

Instance Method Details

#enable_modifications_cacheObject



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'library/network/src/lib/y2firewall/firewalld/relations.rb', line 6

def enable_modifications_cache
  # Return an array with all the modified attributes/relations
  define_method "modified" do
    @modified ||= []
  end

  # Mark the given attribute as modified.
  define_method "modified!" do |item|
    @modified << item unless modified.include?(item)
  end

  # Return whether the object has been modified or not. If an argument is
  # given then it returns whether the given attribute or relation has
  # been modififed.
  define_method "modified?" do |*item|
    return !modified.empty? if item.empty?

    modified.include?(item.first)
  end

  # Reset all the modifications
  define_method "untouched!" do
    @modified = []
  end
end

#has_attributes(*attributes, scope: nil, cache: false) ⇒ Object

Defines a set of methods to operate over single-value firewalld attributes like name, description, default_zone... Bang! methods apply the object modifications into the firewalld configuration using the firewalld API.

A modifications cache can be enable with the cache param.

Examples:


class Zone
  extend Relations

  has_attributes :short, :description, :target, cache: true
end

zone = Zone.new

# Return all the declared attributes
zone.attributes #=> [:short, :description, :target]
# Read all the attributes initializing the object
zone.read_attributes
# Obtain the configured zone name (not the object one)
zone.current_short
# Returns whether the zone has been modified since last read or write
zone.modified? #=> false
# Modifies the zone target
zone.target = "DROP"
zone.modified? #=> true
# Apply all the attributes changes in firewalld
zone.apply_attributes_changes!
zone.modified? #=> false
zone.target = "DROP"
zone.modified? #=> true
Reset all the modifications
zone.untouched!
zone.modified? #=> false

Parameters:

  • attributes (Array<Symbol>)

    relation or attribute names

  • scope (String, nil) (defaults to: nil)

    prepend some API calls with the given scope

  • cache (Boolean) (defaults to: false)

    if enabled will define some methods for caching the object modifications



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'library/network/src/lib/y2firewall/firewalld/relations.rb', line 73

def has_attributes(*attributes, scope: nil, cache: false) # rubocop:disable Naming/PredicateName
  scope_method = scope ? "#{scope}_" : ""
  enable_modifications_cache if cache
  define_method "attributes" do
    attributes
  end

  attributes.each do |attribute|
    attr_reader attribute

    define_method "#{attribute}=" do |item|
      return item if public_send(attribute) == item

      instance_variable_set("@#{attribute}", item)

      modified!(attribute) if cache
    end

    define_method "current_#{attribute}" do
      params = ["#{scope_method}#{attribute}"]
      params << name if respond_to?("name")
      api.public_send(*params)
    end
  end

  define_method "read_attributes" do
    attributes.each { |a| instance_variable_set("@#{a}", public_send("current_#{a}")) }
    true
  end

  define_method "apply_attributes_changes!" do
    attributes.each do |attribute|
      next if cache && !modified?(attribute)

      params = ["modify_#{scope_method}#{attribute}"]
      params << name if respond_to?("name")
      params << public_send(attribute)
      api.public_send(*params)
    end
    true
  end
end

#has_many(*relations, scope: nil, cache: false) ⇒ Object

Defines a set of methods to operate over array based firewalld attributes like services, interfaces, protocols, ports... Bang! methods apply the object modifications into the firewalld configuration using the firewalld cmdline API.

A modifications cache can be enable with the cache param. #

Examples:


class Zone
  extend Relations

  has_many :services, cache: true
end

zone = Zone.new

# Return all the declared relations
zone.relations #=> [:services]
# Read all the relations initializing the object
zone.read_relations
# Adds the "ssh" service into the zone object if not present
zone.add_service("ssh")
# Removes the "ssh" service from the zone object
zone.remove_service("ssh")
# List of current firewalld configured services
zone.current_services
# Adds the service "ssh" definitely into the firewalld zone
zone.add_service!("ssh")
# Removes the service "ssh" definitely from firewalld zone
zone.remove_service!("ssh")
Loop through all the services were added to the zone object since
read adding them definitely to firewalld
zone.add_services!
Loop through all the services were removed from the zone object since
read adding them to firewalld
zone.remove_services!
# Returns the list of services added after read
zone.services_to_add
# Returns the list of services removed after read
zone.services_to_remove
# Apply the changes (remove_services! && add_services!)
zone.apply_services_changes!
# Apply all the relations changes
zone.apply_relations_changes!

Parameters:

  • relations (Array<Symbol>)

    relation or attribute names

  • scope (String, nil) (defaults to: nil)

    prepend some API calls with the given scope

  • cache (Boolean) (defaults to: false)

    if enabled will define some methods for caching the object modifications



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'library/network/src/lib/y2firewall/firewalld/relations.rb', line 166

def has_many(*relations, scope: nil, cache: false) # rubocop:disable Naming/PredicateName
  scope = "#{scope}_" if scope
  enable_modifications_cache if cache

  define_method "relations" do
    relations
  end

  define_method "apply_relations_changes!" do
    relations.each { |r| public_send("apply_#{r}_changes!") }
    true
  end

  define_method "read_relations" do
    relations.each { |r| instance_variable_set("@#{r}", public_send("current_#{r}")) }
    true
  end

  relations.each do |relation|
    relation_singularized = relation.to_s.sub(/s$/, "")
    attr_reader relation

    define_method "#{relation}=" do |item|
      return item if public_send(relation) == item

      instance_variable_set("@#{relation}", item)

      modified!(relation) if cache
    end

    define_method "add_#{relation_singularized}" do |item|
      return public_send(relation) if public_send(relation).include?(item)

      modified!(relation) if cache
      public_send(relation) << item
    end

    define_method "remove_#{relation_singularized}" do |item|
      if public_send(relation).delete(item)
        modified!(relation) if cache
        return public_send(relation)
      end

      public_send(relation)
    end

    define_method "current_#{relation}" do
      if scope
        api.public_send("#{scope}#{relation}", name)
      else
        api.public_send("list_#{relation}", name)
      end
    end

    define_method "add_#{relation_singularized}!" do |item|
      api.public_send("add_#{scope}#{relation_singularized}", name, item)
    end

    define_method "remove_#{relation_singularized}!" do |item|
      api.public_send("remove_#{scope}#{relation_singularized}", name, item)
    end

    define_method "add_#{relation}!" do
      public_send("#{relation}_to_add").map { |i| public_send("add_#{relation_singularized}!", i) }
    end

    define_method "remove_#{relation}!" do
      public_send("#{relation}_to_remove").map { |i| public_send("remove_#{relation_singularized}!", i) }
    end

    define_method "#{relation}_to_add" do
      public_send(relation) - public_send("current_#{relation}")
    end

    define_method "#{relation}_to_remove" do
      public_send("current_#{relation}") - public_send(relation)
    end

    define_method "apply_#{relation}_changes!" do
      return if cache && !modified?(relation)

      public_send("remove_#{relation}!")
      public_send("add_#{relation}!")

      modified.delete(relation)
    end
  end
end