Class: PublishToWeb

Inherits:
Object
  • Object
show all
Defined in:
lib/publish_to_web.rb,
lib/publish_to_web/config.rb,
lib/publish_to_web/tunnel.rb,
lib/publish_to_web/version.rb,
lib/publish_to_web/directory.rb

Defined Under Namespace

Classes: Config, Directory, Tunnel

Constant Summary collapse

SLD =
Regexp.escape '.protonet.info'
VERSION =
"2.5.0"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(forward_port: 80, bind_host: "127.0.0.1", proxy_host: "proxy.protonet.info", proxy_user: "localtunnel", proxy_port: 22666, directory_host: "https://directory.protonet.info", config: Config.new, logger: self.class.create_logger) ⇒ PublishToWeb



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/publish_to_web.rb', line 38

def initialize(
    forward_port: 80,
    bind_host: "127.0.0.1",
    proxy_host: "proxy.protonet.info",
    proxy_user: "localtunnel",
    proxy_port: 22666,
    directory_host: "https://directory.protonet.info",
    config: Config.new,
    logger: self.class.create_logger
  )

  @forward_port   = forward_port
  @bind_host      = bind_host
  @proxy_host     = proxy_host
  @proxy_user     = proxy_user
  @proxy_port     = proxy_port
  @directory_host = directory_host
  @config         = config
  @logger         = logger
end

Instance Attribute Details

#bind_hostObject (readonly)

Returns the value of attribute bind_host.



35
36
37
# File 'lib/publish_to_web.rb', line 35

def bind_host
  @bind_host
end

#configObject (readonly)

Returns the value of attribute config.



35
36
37
# File 'lib/publish_to_web.rb', line 35

def config
  @config
end

#directory_hostObject (readonly)

Returns the value of attribute directory_host.



35
36
37
# File 'lib/publish_to_web.rb', line 35

def directory_host
  @directory_host
end

#forward_portObject (readonly)

Returns the value of attribute forward_port.



35
36
37
# File 'lib/publish_to_web.rb', line 35

def forward_port
  @forward_port
end

#loggerObject (readonly)

Returns the value of attribute logger.



35
36
37
# File 'lib/publish_to_web.rb', line 35

def logger
  @logger
end

#proxy_hostObject (readonly)

Returns the value of attribute proxy_host.



35
36
37
# File 'lib/publish_to_web.rb', line 35

def proxy_host
  @proxy_host
end

#proxy_portObject (readonly)

Returns the value of attribute proxy_port.



35
36
37
# File 'lib/publish_to_web.rb', line 35

def proxy_port
  @proxy_port
end

#proxy_userObject (readonly)

Returns the value of attribute proxy_user.



35
36
37
# File 'lib/publish_to_web.rb', line 35

def proxy_user
  @proxy_user
end

Class Method Details

.create_loggerObject



21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/publish_to_web.rb', line 21

def self.create_logger
  Logger.new(STDOUT).tap do |logger|
    logger.level = Logger::INFO
    logger.formatter = -> (severity, datetime, progname, msg) do
      color = {
        "WARN"  => :yellow,
        "ERROR" => :red,
        "FATAL" => :red
      }[severity] || :white
      Rainbow("[#{datetime}][#{severity.ljust(5)}] #{msg}\n").color(color)
    end
  end
end

Instance Method Details

#check_local_endpointObject



59
60
61
62
63
64
65
66
67
68
# File 'lib/publish_to_web.rb', line 59

def check_local_endpoint
  logger.info "Checking if local backend is available at #{bind_host}:#{forward_port}"
  TCPSocket.new(bind_host, forward_port).close
  logger.info "  ✔ Local backend is available!"

rescue Errno::ECONNREFUSED
  logger.warn "Local backend is not available (yet?) - waiting for it to become available"
  sleep 5
  check_local_endpoint
end

#prepare_directory(fail_gracefully = true) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/publish_to_web.rb', line 71

def prepare_directory(fail_gracefully = true)
  config.success = config.error = nil

  if node_name = config.node_name
    if /^#{ Regexp.escape node_name }(#{ SLD })?$/ !~ directory.node_name
      directory.set_node_name node_name
    end
  end
  directory.set_version
  directory.public_key

  logger.info "Updating SMTP configuration"
  directory.smtp_config.tap do |smtp|
    config.smtp_host   = smtp["host"]
    config.smtp_sender = smtp["sender"]
    config.smtp_user   = smtp["user"]
    config.smtp_pass   = smtp["password"]
  end

  logger.info "Updating limits configuration"
  if limits = directory.limits
    config. = limits["accounts"]
  end

  directory.report_usage

  config.success = 'directory_configured'

rescue PublishToWeb::Directory::HttpResponseError => err
  logger.warn "#{err.class}: #{err}"
  logger.warn "Failed to interact with directory, will try again in a bit"

  # Write out that we have an issue since the directory might refuse
  # our license, our chosen node name might be in conflict and so on
  config.error = "directory_failure.#{err.response.status.to_i}"

  raise unless fail_gracefully
end

#start_tunnel(blocking: true) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/publish_to_web.rb', line 115

def start_tunnel(blocking: true)
  unless blocking
    @thread = Thread.new do
      begin
        start_tunnel blocking: true
        logger.warn "Tunnel closed... :/"
      end while tunnel.running? and sleep(5)
    end
    @thread.abort_on_exception = true
    return
  end

  prepare_directory false
  check_local_endpoint

  logger.info "Starting tunnel to #{proxy_host} as #{directory.node_name}"
  tunnel.start { config.success = "connection_established" }

rescue Net::SSH::AuthenticationFailed => err

  logger.warn "#{err.class}: #{err}"
  logger.warn "Probably the SSH key is not deployed on the proxy server yet, retrying in a bit"

  sleep 30
  retry

rescue PublishToWeb::Directory::HttpResponseError
  # already handled by #prepare_directory, we just need to wait and retry...

  sleep 30
  retry

rescue => error

  logger.error error.message
  logger.error error.backtrace.join("\n")

end

#stop_tunnel(*join_args) ⇒ Object



110
111
112
113
# File 'lib/publish_to_web.rb', line 110

def stop_tunnel(*join_args)
  tunnel.stop
  @thread.join *join_args if @thread
end