Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented ProviderConnect Spec #153

Merged
merged 4 commits into from
Apr 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 171 additions & 0 deletions lua/netman/api.lua
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,36 @@ local _provider_required_attributes = {
, 'get_metadata'
}

--- WARN: Do not rely on these functions existing
--- WARN: Do not use these functions in your code
--- WARN: If you put an issue in saying anything about using
--- these functions is not working in your plugin, you will
--- be laughed at and ridiculed
function M.internal.wrap_shell_handle(handle)
local return_handle = {
read = nil,
write = nil,
stop = nil,
_handle = handle,
_stopped = false
}

function return_handle.read(pipe)
return return_handle._handle and return_handle._handle.read(pipe)
end

function return_handle.write(data)
return return_handle._handle and return_handle._handle.write(data)
end

function return_handle.stop(force)
return_handle._stopped = true
return return_handle._handle and return_handle._handle.stop(force)
end

return return_handle
end

--- WARN: Do not rely on these functions existing
--- WARN: Do not use these functions in your code
--- WARN: If you put an issue in saying anything about using
Expand Down Expand Up @@ -493,6 +523,147 @@ function M.clear_unused_configs(assume_yes)
if not ran then print("There are currently no unused netman provider configurations") end
end

function M.connect_to_uri_host(uri, callback)
local orig_uri = uri
local provider, cache = nil, nil
uri, provider, cache = M.internal.validate_uri(uri)
if not uri or not provider then
local msg = string.format("Unable to find provider for %s, cannot execute connection", orig_uri)
logger.warn(msg)
local response = { message = msg, is_error = true }
if callback then
callback(response)
return
else
return response
end
end
if not provider.connect_host then
local msg = string.format("Provider %s does not report a `close_host` function. Unable to manually connect host of %s", provider.name, uri)
logger.warn(msg)
local response = { message = msg, is_error = true }
if callback then
callback(response)
return
else
return response
end
end
logger.debugf("Reaching out to %s to connect to the host of %s", provider.name, uri)
local handle = nil
if callback then
if not provider.connect_host_a then
logger.warnf("Provider %s does not support asynchronous host connection", provider.name)
callback(provider.connect_host(uri, cache))
return
else
logger.tracef("Attempting asynchronous connection to host of %s", uri)
handle = provider.connect_host_a(uri, cache, callback)
if not handle then
logger.warnf("Provider %s did not provide a handle for asynchronous host connection. Removing the ability to asynchronously connect to hosts")
provider.connect_host_a = nil
callback()
return
end
if handle.message then
-- This is an error response and _not_ what we are expecting
logger.warn("Received message instead of async handle", { message = handle.message, is_error = handle.is_error})
callback(handle)
return
end
local wrapped_handle = M.internal.wrap_shell_handle(handle)
if not wrapped_handle then
logger.warnf("Provider %s returned an invalid handle for asynchronous connect. Removing the ability to asynchronously connect hosts")
provider.connect_host_a = nil
callback()
return
end
M.emit_event('netman_provider_host_connect', 'netman.api.connect_to_uri_host')
return wrapped_handle
end
end
M.emit_event('netman_provider_host_connect', 'netman.api.connect_to_uri_host')
return provider.connect_host(uri, cache)
end

function M.disconnect_from_uri_host(uri, callback)
local orig_uri = uri
local provider, cache = nil, nil
uri, provider, cache = M.internal.validate_uri(uri)
if not uri or not provider then
local msg = string.format("Unable to find provider for %s, cannot execute disconnection", orig_uri)
logger.warn(msg)
local response = { message = msg, is_error = true }
if callback then
callback(response)
return
else
return response
end
end
if not provider.close_host then
local msg = string.format("Provider %s does not report a `close_host` function. Unable to disconnect host of %s", provider.name, uri)
logger.warn(msg)
local response = { message = msg, is_error = true }
if callback then
callback(response)
return
else
return response
end
end
logger.debugf("Reaching out to %s to disconnect the host of %s", provider.name, uri)
local handle = nil
if callback then
if not provider.close_host_a then
logger.warnf("Provider %s does not support asynchronous host disconnection", provider.name)
callback(provider.close_host(uri, cache))
return
else
handle = provider.close_host_a(uri, cache)
if not handle then
logger.warnf("Provider %s did not provide a handle for asynchronous host disconnection. Removing the ability to asynchronously disconnect hosts")
provider.close_host_a = nil
callback()
return
end
if handle.message then
-- This is an error response and _not_ what we are expecting
logger.warn("Received message instead of async handle", { message = handle.message, is_error = handle.is_error })
callback(handle)
return
end
local wrapped_handle = M.internal.wrap_shell_handle(handle)
if not wrapped_handle then
logger.warnf("Provider %s returned an invalid handle for asynchronous disconnect. Removing the ability to asynchronously disconnect hosts")
provider.close_host_a = nil
callback()
return
end
M.emit_event('netman_provider_host_disconnect', 'netman.api.disconnect_from_uri_host')
return wrapped_handle
end
end
M.emit_event('netman_provider_host_disconnect', 'netman.api.disconnect_from_uri_host')
return provider.close_host(uri, cache)
end

function M.has_connection_to_uri_host(uri)
local orig_uri = uri
local provider, cache = nil, nil
uri, provider, cache = M.internal.validate_uri(uri)
if not uri or not provider then
logger.warnf("Unable to find provider for %s, cannot verify connection status", orig_uri)
return nil
end
if not provider.is_connected then
logger.infof("Provider %s does not report an `is_connected` function. Unable to verify connection status of %s", provider.name, uri)
return false
end
logger.debugf("Reaching out to %s to verify connection status of %s", provider.name, uri)
return provider.is_connected(uri, cache)
end

--- TODO: Where Doc?
function M.read(uri, opts)
local orig_uri = uri
Expand Down
31 changes: 27 additions & 4 deletions lua/netman/providers/ssh.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1931,6 +1931,33 @@ function M.delete(uri, cache)
return host:rm(uri, { force = true })
end

function M.connect_host(uri, cache)
-- Just run connect_a and block until complete
local connected = false
local callback = function(success) connected = success end
shell.join(M.connect_host_a(uri, cache, callback))
return connected
end

function M.connect_host_a(uri, cache, exit_callback)
local host = nil
local validation = M.internal.validate(uri, cache)
if validation.error then return validation end
uri = validation.uri
host = validation.host
local callback = function(response)
exit_callback(response and response.success)
end
return host:stat(uri, nil, {
async = true,
finish_callback = callback
})
end

function M.close_connection(uri, cache)

end

function M.get_metadata(uri, cache)
local host = nil
local validation = M.internal.validate(uri, cache)
Expand Down Expand Up @@ -2031,10 +2058,6 @@ function M.archive.schemes(uri, cache)
return host.archive_schemes
end

function M.close_connection(uri, cache)

end

function M.init(config)
M.internal.prepare_config(config)
M.internal.parse_user_sshconfig(config)
Expand Down