<commit_before>require 'fog'
require 'chef/mash'
require 'chef/mixin/deep_merge'
require 'knife-cloudformation'

module KnifeCloudformation
  # Remote provider interface
  class Provider

    # Default stack status filters
    DEFAULT_STACK_STATUS = {
      Fog::AWS::CloudFormation::Real => {
        :status => %w(
          CREATE_IN_PROGRESS CREATE_COMPLETE CREATE_FAILED
          ROLLBACK_IN_PROGRESS ROLLBACK_COMPLETE ROLLBACK_FAILED
          UPDATE_IN_PROGRESS UPDATE_COMPLETE UPDATE_COMPLETE_CLEANUP_IN_PROGRESS
          UPDATE_ROLLBACK_IN_PROGRESS UPDATE_ROLLBACK_FAILED
          UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS UPDATE_ROLLBACK_COMPLETE
          DELETE_IN_PROGRESS DELETE_FAILED
        ),
        :formatter => lambda{|statuses|
          args = statuses.size.times.map do |i|
            idx = i + 1
            ["StackStatusFilter.member.#{idx}", statuses[i]]
          end
          Hash[args]
        }
      }
    }

    # @return [Fog::Orchestration]
    attr_reader :connection
    # @return [Cache]
    attr_reader :cache
    # @return [Thread, NilClass] stack list updater
    attr_accessor :updater
    # @return [TrueClass, FalseClass] async updates
    attr_reader :async

    # Create new instance
    #
    # @param args [Hash]
    # @option args [Hash] :fog fog connection hash
    # @option args [Cache] :cache
    # @option args [TrueClass, FalseClass] :async fetch stacks async (defaults true)
    def initialize(args={})
      unless(args[:fog][:provider])
        best_guess = args[:fog].keys.group_by do |key|
          key.to_s.split('_').first
        end.sort do |x, y|
          y.size <=> x.size
        end.first
        if(best_guess)
          args[:fog][:provider] = best_guess.first
        else
          raise ArgumentError.new 'Cannot auto determine :provider value for credentials'
        end
      end
      @connection = Fog::Orchestration.new(args[:fog])
      @cache = args.fetch(:cache, Cache.new(:local))
      @async = args.fetch(:async, true)
      cache.init(:stacks_lock, :lock)
      cache.init(:stacks, :stamped)
      cache.init(:stack_expansion_lock, :lock)
      async ? update_stack_list! : fetch_stacks
    end

    # @return [Fog::Orchestration::Stacks]
    def stacks
      connection.service.const_get(:Stacks).
        new(:service => connection).
        load(cached_stacks.values).map do |_stack|
        _stack._provider(self)
        _stack
      end
    end

    # @return [Hash] cached stacks
    def cached_stacks
      value = cache[:stacks].value
      value ? MultiJson.load(value) : {}
    end

    # @return [Fog::Orchestration::Stack, NilClass]
    def stack(stack_id)
      attributes = cached_stacks[stack_id]
      if(attributes)
        stack = connection.service.const_get(:Stack).new(
          {:service => connection}.merge(attributes)
        )
        stack._provider(self)
        stack.full_expansion!
      end
    end

    # Store stack attribute changes
    #
    # @param stack_id [String]
    # @param stack_attributes [Hash]
    # @return [TrueClass]
    def save_expanded_stack(stack_id, stack_attributes)
      current_stacks = cached_stacks
      cache.locked_action(:stacks_lock) do
        current_stacks[stack_id] = Chef::Mixin::DeepMerge.merge(
          current_stacks[stack_id],<commit_msg>Return the stacks collection, not the map result array.<commit_after>require 'fog'
require 'chef/mash'
require 'chef/mixin/deep_merge'
require 'knife-cloudformation'

module KnifeCloudformation
  # Remote provider interface
  class Provider

    # Default stack status filters
    DEFAULT_STACK_STATUS = {
      Fog::AWS::CloudFormation::Real => {
        :status => %w(
          CREATE_IN_PROGRESS CREATE_COMPLETE CREATE_FAILED
          ROLLBACK_IN_PROGRESS ROLLBACK_COMPLETE ROLLBACK_FAILED
          UPDATE_IN_PROGRESS UPDATE_COMPLETE UPDATE_COMPLETE_CLEANUP_IN_PROGRESS
          UPDATE_ROLLBACK_IN_PROGRESS UPDATE_ROLLBACK_FAILED
          UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS UPDATE_ROLLBACK_COMPLETE
          DELETE_IN_PROGRESS DELETE_FAILED
        ),
        :formatter => lambda{|statuses|
          args = statuses.size.times.map do |i|
            idx = i + 1
            ["StackStatusFilter.member.#{idx}", statuses[i]]
          end
          Hash[args]
        }
      }
    }

    # @return [Fog::Orchestration]
    attr_reader :connection
    # @return [Cache]
    attr_reader :cache
    # @return [Thread, NilClass] stack list updater
    attr_accessor :updater
    # @return [TrueClass, FalseClass] async updates
    attr_reader :async

    # Create new instance
    #
    # @param args [Hash]
    # @option args [Hash] :fog fog connection hash
    # @option args [Cache] :cache
    # @option args [TrueClass, FalseClass] :async fetch stacks async (defaults true)
    def initialize(args={})
      unless(args[:fog][:provider])
        best_guess = args[:fog].keys.group_by do |key|
          key.to_s.split('_').first
        end.sort do |x, y|
          y.size <=> x.size
        end.first
        if(best_guess)
          args[:fog][:provider] = best_guess.first
        else
          raise ArgumentError.new 'Cannot auto determine :provider value for credentials'
        end
      end
      @connection = Fog::Orchestration.new(args[:fog])
      @cache = args.fetch(:cache, Cache.new(:local))
      @async = args.fetch(:async, true)
      cache.init(:stacks_lock, :lock)
      cache.init(:stacks, :stamped)
      cache.init(:stack_expansion_lock, :lock)
      async ? update_stack_list! : fetch_stacks
    end

    # @return [Fog::Orchestration::Stacks]
    def stacks
      _stacks = connection.service.const_get(:Stacks).
        new(:service => connection).
        load(cached_stacks.values)
      _stacks.map do |_stack|
        _stack._provider(self)
        _stack
      end
      _stacks
    end

    # @return [Hash] cached stacks
    def cached_stacks
      value = cache[:stacks].value
      value ? MultiJson.load(value) : {}
    end

    # @return [Fog::Orchestration::Stack, NilClass]
    def stack(stack_id)
      attributes = cached_stacks[stack_id]
      if(attributes)
        stack = connection.service.const_get(:Stack).new(
          {:service => connection}.merge(attributes)
        )
        stack._provider(self)
        stack.full_expansion!
      end
    end

    # Store stack attribute changes
    #
    # @param stack_id [String]
    # @param stack_attributes [Hash]
    # @return [TrueClass]
    def save_expanded_stack(stack_id, stack_attributes)
      current_stacks = cached_stacks
      cache.locked_action(:stacks_lock) do
        current_stacks[stack_id] = Chef::Mixin::DeepMerge.merge(
          current_stacks[stack_id],
{'fraction_non_alphanumeric': 0.09940387481371088, 'fraction_numerical': 0.00029806259314456036, 'mean_word_length': 2.671225382932166, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2474930', 'n_tokens_mistral': 2154, 'n_tokens_neox': 2106, 'n_words': 436}