Commit 0e158c78 authored by ap4y's avatar ap4y

Add thin model around NetworkPolicy k8s resource

parent 9b1270af
# frozen_string_literal: true
module Gitlab
module Kubernetes
class NetworkPolicy
def initialize(name:, namespace:, pod_selector:, ingress:, creation_timestamp: nil, policy_types: ["Ingress"], egress: nil)
@name = name
@namespace = namespace
@creation_timestamp = creation_timestamp
@pod_selector = pod_selector
@policy_types = policy_types
@ingress = ingress
@egress = egress
end
def self.from_yaml(manifest)
return unless manifest
policy = YAML.safe_load(manifest, symbolize_names: true)
return if !policy[:metadata] || !policy[:spec]
metadata = policy[:metadata]
spec = policy[:spec]
self.new(
name: metadata[:name],
namespace: metadata[:namespace],
pod_selector: spec[:podSelector],
policy_types: spec[:policyTypes],
ingress: spec[:ingress],
egress: spec[:egress]
)
rescue Psych::SyntaxError, Psych::DisallowedClass
nil
end
def self.from_resource(resource)
return unless resource
return if !resource[:metadata] || !resource[:spec]
metadata = resource[:metadata]
spec = resource[:spec].to_h
self.new(
name: metadata[:name],
namespace: metadata[:namespace],
creation_timestamp: metadata[:creationTimestamp],
pod_selector: spec[:podSelector],
policy_types: spec[:policyTypes],
ingress: spec[:ingress],
egress: spec[:egress]
)
end
def generate
::Kubeclient::Resource.new.tap do |resource|
resource.metadata = metadata
resource.spec = spec
end
end
def as_json(opts = nil)
{
name: name,
namespace: namespace,
creation_timestamp: creation_timestamp,
manifest: manifest
}
end
private
attr_reader :name, :namespace, :creation_timestamp, :pod_selector, :policy_types, :ingress, :egress
def metadata
{ name: name, namespace: namespace }
end
def spec
{
podSelector: pod_selector,
policyTypes: policy_types,
ingress: ingress,
egress: egress
}
end
def manifest
YAML.dump(metadata: metadata, spec: spec)
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::Kubernetes::NetworkPolicy do
let(:policy) do
described_class.new(
name: name,
namespace: namespace,
creation_timestamp: '2020-04-14T00:08:30Z',
pod_selector: pod_selector,
policy_types: %w(Ingress Egress),
ingress: ingress,
egress: egress
)
end
let(:name) { 'example-name' }
let(:namespace) { 'example-namespace' }
let(:pod_selector) { { matchLabels: { role: 'db' } } }
let(:ingress) do
[
{
from: [
{ namespaceSelector: { matchLabels: { project: 'myproject' } } }
]
}
]
end
let(:egress) do
[
{
ports: [{ port: 5978 }]
}
]
end
describe '.from_yaml' do
let(:manifest) do
<<-POLICY
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: example-name
namespace: example-namespace
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
project: myproject
POLICY
end
let(:resource) do
::Kubeclient::Resource.new(
metadata: { name: name, namespace: namespace },
spec: { podSelector: pod_selector, policyTypes: %w(Ingress), ingress: ingress, egress: nil }
)
end
subject { Gitlab::Kubernetes::NetworkPolicy.from_yaml(manifest)&.generate }
it { is_expected.to eq(resource) }
context 'with nil manifest' do
let(:manifest) { nil }
it { is_expected.to be_nil }
end
context 'with invalid manifest' do
let(:manifest) { "\tfoo: bar" }
it { is_expected.to be_nil }
end
context 'with manifest without metadata' do
let(:manifest) do
<<-POLICY
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
project: myproject
POLICY
end
it { is_expected.to be_nil }
end
context 'with manifest without spec' do
let(:manifest) do
<<-POLICY
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: example-name
namespace: example-namespace
POLICY
end
it { is_expected.to be_nil }
end
context 'with disallowed class' do
let(:manifest) do
<<-POLICY
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: example-name
namespace: example-namespace
creationTimestamp: 2020-04-14T00:08:30Z
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
project: myproject
POLICY
end
it { is_expected.to be_nil }
end
end
describe '.from_resource' do
let(:resource) do
::Kubeclient::Resource.new(
metadata: { name: name, namespace: namespace, creationTimestamp: '2020-04-14T00:08:30Z', resourceVersion: '4990' },
spec: { podSelector: pod_selector, policyTypes: %w(Ingress), ingress: ingress, egress: nil }
)
end
let(:generated_resource) do
::Kubeclient::Resource.new(
metadata: { name: name, namespace: namespace },
spec: { podSelector: pod_selector, policyTypes: %w(Ingress), ingress: ingress, egress: nil }
)
end
subject { Gitlab::Kubernetes::NetworkPolicy.from_resource(resource)&.generate }
it { is_expected.to eq(generated_resource) }
context 'with nil resource' do
let(:resource) { nil }
it { is_expected.to be_nil }
end
context 'with resource without metadata' do
let(:resource) do
::Kubeclient::Resource.new(
spec: { podSelector: pod_selector, policyTypes: %w(Ingress), ingress: ingress, egress: nil }
)
end
it { is_expected.to be_nil }
end
context 'with resource without spec' do
let(:resource) do
::Kubeclient::Resource.new(
metadata: { name: name, namespace: namespace, uid: '128cf288-7de4-11ea-aceb-42010a800089', resourceVersion: '4990' }
)
end
it { is_expected.to be_nil }
end
end
describe '#generate' do
let(:resource) do
::Kubeclient::Resource.new(
metadata: { name: name, namespace: namespace },
spec: { podSelector: pod_selector, policyTypes: %w(Ingress Egress), ingress: ingress, egress: egress }
)
end
subject { policy.generate }
it { is_expected.to eq(resource) }
end
describe '#as_json' do
let(:json_policy) do
{
name: name,
namespace: namespace,
creation_timestamp: '2020-04-14T00:08:30Z',
manifest: YAML.dump(
{
metadata: { name: name, namespace: namespace },
spec: { podSelector: pod_selector, policyTypes: %w(Ingress Egress), ingress: ingress, egress: egress }
}
)
}
end
subject { policy.as_json }
it { is_expected.to eq(json_policy) }
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment