remocon 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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