Commit d08f439f authored by ap4y's avatar ap4y

Implement NetworkPolicy related services

This patch adds CRUD services for NetworkPolicy k8s resources which
will be used in the corresponding endpoints.
parent 340e78b8
# frozen_string_literal: true
module NetworkPolicies
class DeleteResourceService
include NetworkPolicies::Responses
def initialize(resource_name:, environment:)
@resource_name = resource_name
@platform = environment.deployment_platform
@kubernetes_namespace = environment.deployment_namespace
end
def execute
return no_platform_response unless @platform
@platform.kubeclient.delete_network_policy(@resource_name, @kubernetes_namespace)
ServiceResponse.success
rescue Kubeclient::HttpError => e
kubernetes_error_response(e)
end
end
end
# frozen_string_literal: true
module NetworkPolicies
class DeployResourceService
include NetworkPolicies::Responses
def initialize(policy:, environment:, resource_name: nil)
@policy = policy
@platform = environment.deployment_platform
@kubernetes_namespace = environment.deployment_namespace
@resource_name = resource_name
end
def execute
return empty_resource_response unless policy
return no_platform_response unless platform
setup_resource
resource = deploy_resource
policy = Gitlab::Kubernetes::NetworkPolicy.from_resource(resource)
ServiceResponse.success(payload: policy)
rescue Kubeclient::HttpError => e
kubernetes_error_response(e)
end
private
attr_reader :platform, :policy, :resource_name, :resource, :kubernetes_namespace
def setup_resource
@resource = policy.generate
resource[:metadata][:namespace] = kubernetes_namespace
resource[:metadata][:name] = resource_name if resource_name
end
def deploy_resource
if resource_name
platform.kubeclient.update_network_policy(resource)
else
platform.kubeclient.create_network_policy(resource)
end
end
end
end
# frozen_string_literal: true
module NetworkPolicies
class ResourcesService
include NetworkPolicies::Responses
def initialize(environment:)
@platform = environment.deployment_platform
@kubernetes_namespace = environment.deployment_namespace
end
def execute
return no_platform_response unless @platform
policies = @platform.kubeclient
.get_network_policies(namespace: @kubernetes_namespace)
.map { |resource| Gitlab::Kubernetes::NetworkPolicy.from_resource(resource) }
ServiceResponse.success(payload: policies)
rescue Kubeclient::HttpError => e
kubernetes_error_response(e)
end
end
end
# frozen_string_literal: true
module NetworkPolicies
module Responses
def kubernetes_error_response(error)
ServiceResponse.error(
http_status: :bad_request,
message: s_('NetworkPolicies|Kubernetes error: %{error}') % { error: error }
)
end
def empty_resource_response
ServiceResponse.error(
http_status: :bad_request,
message: s_('NetworkPolicies|Invalid or empty policy')
)
end
def no_platform_response
ServiceResponse.error(
http_status: :bad_request,
message: s_('NetworkPolicies|Environment does not have deployment platform')
)
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe NetworkPolicies::DeleteResourceService do
let(:service) { NetworkPolicies::DeleteResourceService.new(resource_name: 'policy', environment: environment) }
let(:environment) { instance_double('Environment', deployment_platform: platform, deployment_namespace: 'namespace') }
let(:platform) { instance_double('Clusters::Platforms::Kubernetes', kubeclient: kubeclient) }
let(:kubeclient) { double('Kubeclient::Client') }
describe '#execute' do
subject { service.execute }
it 'deletes resource from the deployment namespace and returns success response' do
expect(kubeclient).to receive(:delete_network_policy).with('policy', environment.deployment_namespace)
expect(subject).to be_success
end
context 'without deployment_platform' do
let(:platform) { nil }
it 'returns error response' do
expect(subject).to be_error
expect(subject.http_status).to eq(:bad_request)
expect(subject.message).not_to be_nil
end
end
context 'with Kubeclient::HttpError' do
before do
allow(kubeclient).to receive(:delete_network_policy).and_raise(Kubeclient::HttpError.new(500, 'system failure', nil))
end
it 'returns error response' do
expect(subject).to be_error
expect(subject.http_status).to eq(:bad_request)
expect(subject.message).not_to be_nil
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe NetworkPolicies::DeployResourceService do
let(:service) { NetworkPolicies::DeployResourceService.new(policy: policy, environment: environment) }
let(:environment) { instance_double('Environment', deployment_platform: platform, deployment_namespace: 'namespace') }
let(:platform) { instance_double('Clusters::Platforms::Kubernetes', kubeclient: kubeclient) }
let(:kubeclient) { double('Kubeclient::Client') }
let(:policy) do
Gitlab::Kubernetes::NetworkPolicy.new(
name: 'policy',
namespace: 'another',
pod_selector: { matchLabels: { role: 'db' } },
ingress: [{ from: [{ namespaceSelector: { matchLabels: { project: 'myproject' } } }] }]
)
end
describe '#execute' do
subject { service.execute }
it 'creates resource in the deployment namespace and return success response with a policy' do
namespaced_policy = policy.generate
namespaced_policy[:metadata][:namespace] = environment.deployment_namespace
expect(kubeclient).to receive(:create_network_policy).with(namespaced_policy) { policy.generate }
expect(subject).to be_success
expect(subject.payload.as_json).to eq(policy.as_json)
end
context 'with resource_name' do
let(:service) { NetworkPolicies::DeployResourceService.new(policy: policy, environment: environment, resource_name: 'policy2') }
it 'updates resource in the deployment namespace and returns success response with a policy' do
namespaced_policy = policy.generate
namespaced_policy[:metadata][:namespace] = environment.deployment_namespace
namespaced_policy[:metadata][:name] = 'policy2'
expect(kubeclient).to receive(:update_network_policy).with(namespaced_policy) { policy.generate }
expect(subject).to be_success
expect(subject.payload.as_json).to eq(policy.as_json)
end
end
context 'without policy' do
let(:policy) { nil }
it 'returns error response' do
expect(subject).to be_error
expect(subject.http_status).to eq(:bad_request)
expect(subject.message).not_to be_nil
end
end
context 'without deployment_platform' do
let(:platform) { nil }
it 'returns error response' do
expect(subject).to be_error
expect(subject.http_status).to eq(:bad_request)
expect(subject.message).not_to be_nil
end
end
context 'with Kubeclient::HttpError' do
before do
allow(kubeclient).to receive(:create_network_policy).and_raise(Kubeclient::HttpError.new(500, 'system failure', nil))
end
it 'returns error response' do
expect(subject).to be_error
expect(subject.http_status).to eq(:bad_request)
expect(subject.message).not_to be_nil
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe NetworkPolicies::ResourcesService do
let(:service) { NetworkPolicies::ResourcesService.new(environment: environment) }
let(:environment) { instance_double('Environment', deployment_platform: platform, deployment_namespace: 'namespace') }
let(:platform) { instance_double('Clusters::Platforms::Kubernetes', kubeclient: kubeclient) }
let(:kubeclient) { double('Kubeclient::Client') }
let(:policy) do
Gitlab::Kubernetes::NetworkPolicy.new(
name: 'policy',
namespace: 'another',
pod_selector: { matchLabels: { role: 'db' } },
ingress: [{ from: [{ namespaceSelector: { matchLabels: { project: 'myproject' } } }] }]
)
end
describe '#execute' do
subject { service.execute }
it 'returns success response with policies from the deployment namespace' do
expect(kubeclient).to receive(:get_network_policies).with(namespace: environment.deployment_namespace) { [policy.generate] }
expect(subject).to be_success
expect(subject.payload.count).to eq(1)
expect(subject.payload.first.as_json).to eq(policy.as_json)
end
context 'without deployment_platform' do
let(:platform) { nil }
it 'returns error response' do
expect(subject).to be_error
expect(subject.http_status).to eq(:bad_request)
expect(subject.message).not_to be_nil
end
end
context 'with Kubeclient::HttpError' do
before do
allow(kubeclient).to receive(:get_network_policies).and_raise(Kubeclient::HttpError.new(500, 'system failure', nil))
end
it 'returns error response' do
expect(subject).to be_error
expect(subject.http_status).to eq(:bad_request)
expect(subject.message).not_to be_nil
end
end
end
end
......@@ -84,7 +84,7 @@ module Gitlab
end
def manifest
YAML.dump(metadata: metadata, spec: spec)
YAML.dump({ metadata: metadata, spec: spec }.deep_stringify_keys)
end
end
end
......
......@@ -13827,6 +13827,15 @@ msgstr ""
msgid "Network"
msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
msgid "NetworkPolicies|Invalid or empty policy"
msgstr ""
msgid "NetworkPolicies|Kubernetes error: %{error}"
msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
......
......@@ -212,7 +212,7 @@ spec:
{
metadata: { name: name, namespace: namespace },
spec: { podSelector: pod_selector, policyTypes: %w(Ingress Egress), ingress: ingress, egress: egress }
}
}.deep_stringify_keys
)
}
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