class Biosphere::Kube::KubeResource

Encapsulates a single resource inside kube apiserver (eg. a Deployment or a DaemonSet). A KubeResource comes from a manifest which has one or more resources (yaml allows separating multiple documents with — inside a single file).

Attributes

document[RW]
preserve_current_values[RW]
resource[RW]
source_file[RW]

Public Class Methods

new(document, source_file) click to toggle source
# File lib/biosphere/kube.rb, line 39
def initialize(document, source_file)
    @document = document
    @source_file = source_file
    @preserve_current_values = []
end

Public Instance Methods

merge_for_put(current) click to toggle source

Merges the resource with the current resource version in the api server, which has important properties such as:

- metadata.selfLink
- metadata.uid
- metadata.resourceVersion

A document can’t be updated (PUT verb) unless these are carried over

# File lib/biosphere/kube.rb, line 53
def merge_for_put(current)
    new_version = DeepDup.deep_dup(@document)

    if current["metadata"]
        new_version["metadata"]["selfLink"] = current["metadata"]["selfLink"] if current["metadata"]["selfLink"]
        new_version["metadata"]["uid"] = current["metadata"]["uid"] if current["metadata"]["uid"]
        new_version["metadata"]["resourceVersion"] = current["metadata"]["resourceVersion"] if current["metadata"]["resourceVersion"]
    end

    if current["spec"]
        new_version["spec"] = {} if !new_version["spec"]

        # handle spec.clusterIP
        if new_version["spec"]["clusterIP"] && new_version["spec"]["clusterIP"] != current["spec"]["clusterIP"]
            raise ArgumentError, "#{@source_file}: Tried to modify spec.clusterIP from #{current["spec"]["clusterIP"]} to #{new_version["spec"]["clusterIP"]} but the field is immutable"
        end
        new_version["spec"]["clusterIP"] = current["spec"]["clusterIP"] if current["spec"]["clusterIP"]

    end

    @preserve_current_values.each do |jsonpath_query|
        jp = JsonPath.new(jsonpath_query)
        current_value = jp.on(current)
        if current_value.length > 1
            raise ArgumentError, "#{@source_file}: A JSONPath query \"#{jsonpath_query}\" matched more than one element: #{current_value}. This is not allowed because it should be used to preserve the current value in the Kubernets API server for the property."
        end

        new_value = jp.on(new_version)
        if new_value.length > 1
            raise ArgumentError, "#{@source_file}: A JSONPath query \"#{jsonpath_query}\" matched more than one element: #{new_value}. This is not allowed because it should be used to preserve the current value in the Kubernets API server for the property."
        end

        if current_value.first != new_value.first
            new_version = JsonPath.for(new_version).gsub(jsonpath_query) { |proposed_value| current_value.first }.to_hash
        end
    end

    return new_version
end