remocon 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,8 +3,10 @@
3
3
  set -eu
4
4
 
5
5
  if type easy_install >/dev/null 2>&1; then
6
+ sudo easy_install --upgrade oauth2client
6
7
  sudo easy_install --upgrade google-api-python-client
7
8
  else
9
+ sudo pip install --upgrade oauth2client
8
10
  sudo pip install --upgrade google-api-python-client
9
11
  fi
10
12
 
@@ -7,7 +7,7 @@ from oauth2client.service_account import ServiceAccountCredentials
7
7
 
8
8
  def print_access_token():
9
9
  argv = sys.argv
10
- if (len(argv) != 2):
10
+ if (len(argv) < 1):
11
11
  print >> sys.stderr, 'a filepath to service-account.json must be specified as the 1st argument.'
12
12
  quit()
13
13
  credentials = ServiceAccountCredentials.from_json_keyfile_name(
@@ -15,4 +15,4 @@ def print_access_token():
15
15
  access_token_info = credentials.get_access_token()
16
16
  print(access_token_info.access_token)
17
17
 
18
- print_access_token
18
+ print_access_token()
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'remocon'
4
+ require "remocon"
5
5
 
6
6
  Remocon::CLI.start(ARGV)
@@ -1,47 +1,48 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yaml'
4
- require 'json'
5
- require 'thor'
6
- require 'active_support'
7
- require 'active_support/core_ext'
8
- require 'singleton'
9
- require 'open-uri'
10
- require 'fileutils'
11
- require 'net/http'
12
-
13
- require 'remocon/util/array'
14
- require 'remocon/util/hash'
15
- require 'remocon/util/string'
16
-
17
- require 'remocon/version'
18
- require 'remocon/type'
19
-
20
- require 'remocon/error/unsupported_type_error'
21
- require 'remocon/error/validation_error'
22
-
23
- require 'remocon/sorter/condition_sorter'
24
- require 'remocon/sorter/parameter_sorter'
25
-
26
- require 'remocon/dumper/condition_file_dumper'
27
- require 'remocon/dumper/parameter_file_dumper'
28
-
29
- require 'remocon/interpreter/condition_file_interpreter'
30
- require 'remocon/interpreter/parameter_file_interpreter'
31
-
32
- require 'remocon/normalizer/normalizer'
33
- require 'remocon/normalizer/boolean_normalizer'
34
- require 'remocon/normalizer/integer_normalizer'
35
- require 'remocon/normalizer/json_normalizer'
36
- require 'remocon/normalizer/string_normalizer'
37
- require 'remocon/normalizer/void_normalizer'
38
- require 'remocon/normalizer/type_normalizer_factory'
39
-
40
- require 'remocon/command/lib/interpreter_helper'
41
-
42
- require 'remocon/command/create_command'
43
- require 'remocon/command/pull_command'
44
- require 'remocon/command/push_command'
45
- require 'remocon/command/validate_command'
46
-
47
- require 'remocon/cli'
3
+ require "yaml"
4
+ require "json"
5
+ require "thor"
6
+ require "active_support"
7
+ require "active_support/core_ext"
8
+ require "singleton"
9
+ require "open-uri"
10
+ require "fileutils"
11
+ require "net/http"
12
+
13
+ require "remocon/util/array"
14
+ require "remocon/util/hash"
15
+ require "remocon/util/string"
16
+
17
+ require "remocon/version"
18
+ require "remocon/type"
19
+
20
+ require "remocon/error/unsupported_type_error"
21
+ require "remocon/error/validation_error"
22
+
23
+ require "remocon/sorter/condition_sorter"
24
+ require "remocon/sorter/parameter_sorter"
25
+
26
+ require "remocon/dumper/condition_file_dumper"
27
+ require "remocon/dumper/parameter_file_dumper"
28
+
29
+ require "remocon/interpreter/condition_file_interpreter"
30
+ require "remocon/interpreter/parameter_file_interpreter"
31
+
32
+ require "remocon/normalizer/normalizer"
33
+ require "remocon/normalizer/boolean_normalizer"
34
+ require "remocon/normalizer/integer_normalizer"
35
+ require "remocon/normalizer/json_normalizer"
36
+ require "remocon/normalizer/string_normalizer"
37
+ require "remocon/normalizer/void_normalizer"
38
+ require "remocon/normalizer/type_normalizer_factory"
39
+
40
+ require "remocon/command/lib/config"
41
+ require "remocon/command/lib/interpreter_helper"
42
+
43
+ require "remocon/command/create_command"
44
+ require "remocon/command/pull_command"
45
+ require "remocon/command/push_command"
46
+ require "remocon/command/validate_command"
47
+
48
+ require "remocon/cli"
@@ -2,32 +2,44 @@
2
2
 
3
3
  module Remocon
4
4
  class CLI < ::Thor
5
- desc 'create', 'Create a json to be pushed'
6
- option :parameters, type: :string, required: true, desc: 'a filepath of parameters file'
7
- option :conditions, type: :string, required: true, desc: 'a filepath of conditions file'
8
- option :dest, type: :string, desc: 'a filepath or directory path of destination'
5
+ desc "create", "Create a json to be pushed"
6
+ option :parameters, type: :string, desc: "Specify the filepath if you want to use a custom parameters file"
7
+ option :conditions, type: :string, desc: "Specify the filepath if you want to use a custom conditions file"
8
+ option :prefix, type: :string, desc: "the directory name which will contain project-related files"
9
+ option :id, type: :string, desc: "your project"
10
+ option :dest, type: :string, hide: true, desc: "[Deprecated] the same with --prefix"
9
11
  def create
10
12
  execute(Remocon::Command::Create)
11
13
  end
12
14
 
13
- desc 'push', 'Upload remote configs based on a source json file'
14
- class_option :source, type: :string, desc: 'a filepath of a source json file'
15
- option :etag, type: :string, desc: 'a filepath or raw value of etag'
16
- option :dest, type: :string, desc: 'a filepath or directory path of destination'
17
- option :force, type: :boolean, default: false, desc: 'force to ignore some warnings'
15
+ desc "push", "Upload remote configs based on a source json file"
16
+ option :source, type: :string, desc: "the filepath of your config json file"
17
+ option :etag, type: :string, desc: "the file path of etag"
18
+ option :raw_etag, type: :string, desc: "the raw value of etag"
19
+ option :prefix, type: :string, desc: "the directory name which will contain project-related files"
20
+ option :force, type: :boolean, default: false, desc: "force to ignore some warnings"
21
+ option :token, type: :string, desc: "access token to your project"
22
+ option :id, type: :string, desc: "your project id"
23
+ option :dest, type: :string, hide: true, desc: "[Deprecated] the same with --prefix"
18
24
  def push
19
25
  execute(Remocon::Command::Push)
20
26
  end
21
27
 
22
- desc 'pull', 'Pull remote configs'
23
- option :dest, type: :string, desc: 'a filepath or directory path of destination'
28
+ desc "pull", "Pull remote configs"
29
+ option :prefix, type: :string, desc: "the directory name which will contain project-related files"
30
+ option :token, type: :string, desc: "access token to your project"
31
+ option :id, type: :string, desc: "your project id"
32
+ option :dest, type: :string, hide: true, desc: "[Deprecated] the same with --prefix"
24
33
  def pull
25
34
  execute(Remocon::Command::Pull)
26
35
  end
27
36
 
28
- desc 'validate', 'Validate yml files'
29
- option :parameters, type: :string, required: true, desc: 'a filepath of parameters file'
30
- option :conditions, type: :string, required: true, desc: 'a filepath of conditions file'
37
+ desc "validate", "Validate yml files"
38
+ option :parameters, type: :string, desc: "Specify the filepath if you want to use a custom parameters file"
39
+ option :conditions, type: :string, desc: "Specify the filepath if you want to use a custom conditions file"
40
+ option :prefix, type: :string, desc: "the directory name which will contain project-related files"
41
+ option :id, type: :string, desc: "your project id"
42
+ option :token, type: :string, desc: "access token to your project"
31
43
  def validate
32
44
  execute(Remocon::Command::Validate)
33
45
  end
@@ -35,7 +47,7 @@ module Remocon
35
47
  private
36
48
 
37
49
  def execute(klass)
38
- klass.new(options).run
50
+ exit(1) unless klass.new(options).run
39
51
  end
40
52
  end
41
53
  end
@@ -5,15 +5,19 @@ module Remocon
5
5
  class Create
6
6
  include Remocon::InterpreterHelper
7
7
 
8
+ attr_reader :config, :cmd_opts
9
+
8
10
  def initialize(opts)
9
- @opts = opts
11
+ @config = Remocon::Config.new(opts)
12
+ @cmd_opts = { validate_only: false }
13
+ end
10
14
 
11
- @project_id = ENV.fetch('FIREBASE_PROJECT_ID')
12
- @conditions_filepath = @opts[:conditions]
13
- @parameters_filepath = @opts[:parameters]
14
- @dest_dir = File.join(@opts[:dest], @project_id) if @opts[:dest]
15
+ def require_parameters_file_path
16
+ config.parameters_file_path
17
+ end
15
18
 
16
- @cmd_opts = { validate_only: false }
19
+ def require_conditions_file_path
20
+ config.conditions_file_path
17
21
  end
18
22
 
19
23
  def run
@@ -24,14 +28,10 @@ module Remocon
24
28
  parameters: parameter_hash
25
29
  }.skip_nil_values.stringify_values
26
30
 
27
- if @dest_dir
28
- File.open(File.join(@dest_dir, 'config.json'), 'w+') do |f|
29
- # remote config allows only string values ;(
30
- f.write(JSON.pretty_generate(artifact))
31
- f.flush
32
- end
33
- else
34
- STDOUT.puts JSON.pretty_generate(artifact)
31
+ File.open(config.config_json_file_path, "w+") do |f|
32
+ # remote config allows only string values ;(
33
+ f.write(JSON.pretty_generate(artifact))
34
+ f.flush
35
35
  end
36
36
 
37
37
  artifact
@@ -40,8 +40,8 @@ module Remocon
40
40
  private
41
41
 
42
42
  def validate_options
43
- raise ValidationError, 'A condition file must exist' unless File.exist?(@conditions_filepath)
44
- raise ValidationError, 'A parameter file must exist' unless File.exist?(@parameters_filepath)
43
+ raise ValidationError, "A condition file must exist" unless File.exist?(config.conditions_file_path)
44
+ raise ValidationError, "A parameter file must exist" unless File.exist?(config.parameters_file_path)
45
45
  end
46
46
  end
47
47
  end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Remocon
4
+ class Config
5
+ REMOCON_PROJECT_ID_KEY = "REMOCON_FIREBASE_PROJECT_ID"
6
+ REMOCON_ACCESS_TOKEN = "REMOCON_FIREBASE_ACCESS_TOKEN"
7
+
8
+ REMOCON_PREFIX_KEY = "REMOCON_PREFIX"
9
+
10
+ CONFIG_JSON_FILE = "config.json"
11
+ CONDITIONS_FILE_NAME = "conditions.yml"
12
+ PARAMETERS_FILE_NAME = "parameters.yml"
13
+ ETAG_FILE_NAME = "etag"
14
+
15
+ attr_reader :opts
16
+
17
+ def initialize(opts)
18
+ @opts = opts
19
+ end
20
+
21
+ def endpoint
22
+ @endpoint ||= "https://firebaseremoteconfig.googleapis.com/v1/projects/#{project_id}/remoteConfig"
23
+ end
24
+
25
+ def project_id
26
+ # FIREBASE_PROJECT_ID is for backward compatibility
27
+ @project_id ||= (opts[:id] || ENV[REMOCON_PROJECT_ID_KEY] || ENV["FIREBASE_PROJECT_ID"] || raise("--id or #{REMOCON_PROJECT_ID_KEY} env var is required"))
28
+ end
29
+
30
+ def token
31
+ # REMOTE_CONFIG_ACCESS_TOKEN is for backward compatibility
32
+ @token ||= (opts[:token] || ENV[REMOCON_ACCESS_TOKEN] || ENV["REMOTE_CONFIG_ACCESS_TOKEN"] || raise("--token or #{REMOCON_ACCESS_TOKEN} env var is required"))
33
+ end
34
+
35
+ def destination_dir_path
36
+ @destination_dir_path ||= (opts[:prefix] || opts[:dest] || ENV[REMOCON_PREFIX_KEY])
37
+ end
38
+
39
+ def project_dir_path
40
+ @project_dir_path ||= begin
41
+ dir_path = destination_dir_path
42
+ (dir_path ? File.join(dir_path, project_id) : project_id).tap do |dir|
43
+ FileUtils.mkdir_p(dir)
44
+ end
45
+ end
46
+ end
47
+
48
+ def config_json_file_path
49
+ @config_json_file_path ||= opts[:source] || begin
50
+ File.join(project_dir_path, CONFIG_JSON_FILE)
51
+ end
52
+ end
53
+
54
+ def conditions_file_path
55
+ @conditions_file_path ||= opts[:conditions] || begin
56
+ File.join(project_dir_path, CONDITIONS_FILE_NAME)
57
+ end
58
+ end
59
+
60
+ def parameters_file_path
61
+ @parameters_file_path ||= opts[:parameters] || begin
62
+ File.join(project_dir_path, PARAMETERS_FILE_NAME)
63
+ end
64
+ end
65
+
66
+ def etag_file_path
67
+ @etag_file_path ||= opts[:etag] || begin
68
+ File.join(project_dir_path, ETAG_FILE_NAME)
69
+ end
70
+ end
71
+
72
+ def etag
73
+ @etag ||= begin
74
+ if opts[:force] && opts[:raw_etag]
75
+ raise "--force and --raw_etag cannot be specified"
76
+ end
77
+
78
+ opts[:force] && "*" || opts[:raw_etag] || File.exist?(etag_file_path) && File.open(etag_file_path).read
79
+ end
80
+ end
81
+ end
82
+ end
@@ -5,11 +5,21 @@ module Remocon
5
5
  include Remocon::ConditionSorter
6
6
  include Remocon::ParameterSorter
7
7
 
8
- attr_reader :parameters_filepath, :conditions_filepath, :cmd_opts
8
+ def cmd_opts
9
+ raise NotImplementedError
10
+ end
11
+
12
+ def require_parameters_file_path
13
+ raise NotImplementedError
14
+ end
15
+
16
+ def require_conditions_file_path
17
+ raise NotImplementedError
18
+ end
9
19
 
10
20
  def read_parameters
11
21
  @read_parameters ||= begin
12
- parameter_interpreter = Remocon::ParameterFileInterpreter.new(parameters_filepath)
22
+ parameter_interpreter = Remocon::ParameterFileInterpreter.new(require_parameters_file_path)
13
23
  parameter_interpreter.read(condition_names, cmd_opts)
14
24
  end
15
25
  end
@@ -24,7 +34,7 @@ module Remocon
24
34
 
25
35
  def read_conditions
26
36
  @read_conditions ||= begin
27
- condition_interpreter = Remocon::ConditionFileInterpreter.new(conditions_filepath)
37
+ condition_interpreter = Remocon::ConditionFileInterpreter.new(require_conditions_file_path)
28
38
  condition_interpreter.read(cmd_opts)
29
39
  end
30
40
  end
@@ -5,61 +5,60 @@ module Remocon
5
5
  class Pull
6
6
  include Remocon::InterpreterHelper
7
7
 
8
+ attr_reader :config, :cmd_opts
9
+
8
10
  def initialize(opts)
9
- @opts = opts
11
+ @config = Remocon::Config.new(opts)
12
+ @cmd_opts = { validate_only: false }
13
+ end
10
14
 
11
- @project_id = ENV.fetch('FIREBASE_PROJECT_ID')
12
- @token = ENV.fetch('REMOTE_CONFIG_ACCESS_TOKEN')
13
- @url = "https://firebaseremoteconfig.googleapis.com/v1/projects/#{@project_id}/remoteConfig"
14
- @dest_dir = File.join(@opts[:dest], @project_id) if @opts[:dest]
15
+ def require_parameters_file_path
16
+ config.parameters_file_path
17
+ end
15
18
 
16
- @cmd_opts = { validate_only: false }
19
+ def require_conditions_file_path
20
+ config.conditions_file_path
17
21
  end
18
22
 
19
23
  def run
20
- if @dest_dir
21
- FileUtils.mkdir_p(@dest_dir)
24
+ raw_json, etag = do_request
22
25
 
23
- raw_hash = JSON.parse(raw_json).with_indifferent_access
26
+ raw_hash = JSON.parse(raw_json).with_indifferent_access
24
27
 
25
- raise 'etag cannot be fetched. please try again' unless @etag
28
+ raise "etag cannot be fetched. please try again" unless etag
26
29
 
27
- conditions, parameters = [raw_hash[:conditions] || [], raw_hash[:parameters] || {}]
30
+ conditions = raw_hash[:conditions] || []
31
+ parameters = raw_hash[:parameters] || {}
28
32
 
29
- File.open(File.join(@dest_dir, "conditions.yml"), 'w+') do |f|
30
- f.write(JSON.parse(Remocon::ConditionFileDumper.new(sort_conditions(conditions)).dump.to_json).to_yaml)
31
- f.flush
32
- end
33
+ File.open(config.conditions_file_path, "w+") do |f|
34
+ f.write(JSON.parse(Remocon::ConditionFileDumper.new(sort_conditions(conditions)).dump.to_json).to_yaml)
35
+ f.flush
36
+ end
33
37
 
34
- File.open(File.join(@dest_dir, "parameters.yml"), 'w+') do |f|
35
- f.write(JSON.parse(Remocon::ParameterFileDumper.new(sort_parameters(parameters)).dump.to_json).to_yaml)
36
- f.flush
37
- end
38
+ File.open(config.parameters_file_path, "w+") do |f|
39
+ f.write(JSON.parse(Remocon::ParameterFileDumper.new(sort_parameters(parameters)).dump.to_json).to_yaml)
40
+ f.flush
41
+ end
38
42
 
39
- File.open(File.join(@dest_dir, "config.json"), 'w+') do |f|
40
- f.write(JSON.pretty_generate({ conditions: sort_conditions(conditions), parameters: sort_parameters(parameters) }))
41
- f.flush
42
- end
43
+ File.open(config.config_json_file_path, "w+") do |f|
44
+ f.write(JSON.pretty_generate({ conditions: sort_conditions(conditions), parameters: sort_parameters(parameters) }))
45
+ f.flush
46
+ end
43
47
 
44
- File.open(File.join(@dest_dir, 'etag'), 'w+') do |f|
45
- f.write(@etag)
46
- f.flush
47
- end
48
- else
49
- STDOUT.puts raw_json
48
+ File.open(config.etag_file_path, "w+") do |f|
49
+ f.write(etag)
50
+ f.flush
50
51
  end
51
52
  end
52
53
 
53
54
  private
54
55
 
55
- def raw_json
56
- return @raw_json if @raw_json
57
-
58
- @raw_json, @etag = open(@url, 'Authorization' => "Bearer #{@token}") do |io|
59
- [io.read, io.meta['etag']]
56
+ def do_request
57
+ raw_json, etag = open(config.endpoint, "Authorization" => "Bearer #{config.token}") do |io|
58
+ [io.read, io.meta["etag"]]
60
59
  end
61
60
 
62
- @raw_json
61
+ [raw_json, etag]
63
62
  end
64
63
  end
65
64
  end