cockpit.js

cockpit.js — Basic cockpit API to interact with the system

Loading cockpit.js

cockpit.js should be loaded via a script tag. In general jQuery should be loaded before cockpit.js as in the example below. If jQuery is not loaded then only the raw channel API will be defined.

  <script src="../base1/jquery.js">
  <script src="../base1/cockpit.js">

User Login

cockpit.logout()

  cockpit.logout([reload])

Logout of Cockpit. Unless reload is false this will also cause the page to be reloaded, so that the user can see the logged out state.

cockpit.user

  cockpit.user["user"]
  cockpit.user["name"]
  cockpit.user["groups"]
  cockpit.user["shell"]
  cockpit.user["home"]
  cockpit.user["id"]

This object contains information about the user that's currently logged into cockpit. The following fields are defined:

"groups"

This is an array of group names to which the user belongs.

"home"

This is user's home directory.

"id"

This is unix user id.

"name"

This is a readable name for the user.

"shell"

This is unix user shell.

"user"

This is the unix user like "root".

The fields will be undefined until a connection is made to the cockpit server.

cockpit.user.onchanged

  $(cockpit.user).on("changed", function() { ... })

This event is fired when the user info changes or first becomes available.

Page Location

  location = cockpit.location
  cockpit.location = "/path"

Cockpit components often have different views, without changing the HTML file that is being viewed. These are known as pages. cockpit.location is an object that can be used to read the current page and to navigate to a different page location. It works by updating window.location.hash.

The cockpit.location looks like a HTTP path with a possible query string:

 /path/sub/page?option=value,option2

The location.path and location.options contain a parsed form of the location. While the location cannot be modified in place, a new one can be created by assigning a string to cockpit.location or by calling the location.go() function.

cockpit.location is designed similarly to window.location in that the location object is preplaced whenever the current page location changes. To be aware of when the page location changes listen for the cockpit.onlocationchanged event.

Using the location object as a string will result in the location.href.

location.href

The string representation of this page location, including any options.

location.path

An array of path segments, parsed and decoded appropriately. An empty array denotes the root path.

location.options

A javascript object containing the various options present in the location.

location.go()

  location.go(path, [options])

Changes the current location to the given path and options. If the path argument is a string, it will be parsed into a path. If it is a relative path, then the result will be relative to the current location.path. If the path argument is an array of path segments, it will be treated as a full parsed absolute path.

Any options found in a path will be added to those in the optional options argument, and used in the result.

The location change will only take effect if the location has not changed in the meantime. This can be to good effect by saving a cockpit.location object and doing a conditional navigation, by calling the saved location.go() method later. This will only navigate if the user or other code has not navigated in the meantime.

location.replace()

  location.replace(path, [options])

Similar to location.go() except the location change will not result in a navigation change in the browser's history.

location.decode()

  path = location.decode(href, [options])

Decode a cockpit href into its path array. If the options argument is specified, then it will be populated with options found in the href.

If href is a relative path it will be resolved relative to location.href.

location.encode()

  href = location.encode(path, [options])

Encode the given path and options into a cockpit href. The path argument may be an array of path segments, or a string path. If a relative path is passed, it will be resolved relative to location.href.

cockpit.onlocationchanged

 $(cockpit).on("locationchanged", function() { ... })

An event emitted when over the cockpit.location changes. Typically a component reacts to this event by updating its interface to reflect the new cockpit.location.path and cockpit.location.options.

This event is not triggered immediately during a location.go() or similar call. It will be triggered asynchronously at a later time.

Jumping between components

  cockpit.jump("/system/log")

In Cockpit in there multiple components shown. In order to tell Cockpit to jump to and show another component and a certain location within that component, use the cockpit.jump() function. Stable component paths are documented. Don't assume you can navigate into paths that are not stable API.

cockpit.jump()

  cockpit.jump(path, [ host ])

Ask Cockpit to jump to another component. The location of the current component will not be affected. The path argument can be a string path, starting with / or an array containing the parts of a path that will be joined to create a path. If host is not specified, then the component on the same host as the caller will be displayed.

If the calling component is not running within Cockpit, or the calling component is not currently displayed, then the jump will not happen, and this function has no effect.

Spawning Processes

This is the API for spawning a process and receiving its output, as well as exit codes.

cockpit.spawn()

 process = cockpit.spawn(args, [options])

Spawns a process on the system.

The args should be an array starting with the executable and containing all the arguments to pass on the command line. If args is a string then it is interpreted as an executable name. The optional options argument is a javascript plain object and can contain any of the following fields:

"binary"

If set to true then handle the input and output of the process as arrays of binary bytes.

"directory"

The directory to spawn the process in.

"err"

Controls where the standard error is sent. By default it is logged to the journal. If set to "out" it is included in with the output data. If set to "ignore" then the error output is discarded. When the "pty" field is set, this field has no effect.

"host"

The remote host to spawn the process on. If no host is specified then the correct one will be automatically selected based on the page calling this function.

"environ"

An optional array that contains strings to be used as additional environment variables for the new process. These are "NAME=VALUE" strings.

"pty"

Launch the process in its own PTY terminal, and send/receive terminal input and output.

"batch"

Batch data coming from the process in blocks of at least this size. This is not a guarantee. After a short timeout the data will be sent even if the data doesn't match the batch size. Defaults to zero.

"latency"

The timeout for flushing any cached data in milliseconds.

"superuser"

Try to spawn the process as root instead of the logged in user. If the currently logged in user is not permitted to become root (eg: via pkexec) then the client will immediately be closed with a "access-denied" problem code.

The spawned process is a jQuery promise that will complete if the process exits successfully, or fail if there's a problem. Some additional methods besides the standard jQuery promise methods are documented below.

The standard output of the process is made available via the spawned process object. Any non-UTF8 output from the process will be coerced into textual form. It is highly recommended that only textual output be produced by the command. The standard error is logged to the journal.

process.done()

 process.done(function(data) { ... })

This is a standard jQuery promise method. It sets up a handler to be called when the process finishes successfully.

The data argument contains the standard output of the process. If it a string, unless the process was opened in binary mode, in which case the data is an array of bytes. If a process.stream() handler is set up, then any standard output data consumed by the handler will not be included in the data argument.

process.fail()

 process.fail(function(exception[, data]) { ... })

This is a standard jQuery promise method. It sets up a handler to be called when the process fails, terminates or exits.

The exception object passed to the handler can have the following fields:

problem

A problem code string when a problem occurred starting or communicating with the process. This is null if the process exited or was terminated.

exit_status

The numeric exit status of the process. This is null if the process did not exit.

exit_signal

A string representing a unix signal that caused the process to terminate. This is null if the process did not terminate because of a signal.

If the process actually ran and produced output before failing, it will be available in the data argument. Otherwise this argument will be undefined.

process.always()

 process.always(function() { ... })

This is a standard jQuery promise method. It sets up a handler to be called when when the process completes, whether it exits successfully, fails, terminates, or exits with a failure.

process.stream()

 process.stream(function(data) { ... })

This sets up a handler to be called when the process has standard output. The handler will be called multiple times. The handler will be called regardless of whether the process ends up exiting successfully or not.

Only one handler may be registered at a time. Registering an additional handler replaces the previous one. The handler receives either string data or an array of binary bytes as its argument. A stream handler may return a number, which indicates the number of characters or bytes consumed from data. Any data not consumed will be included again the next time the handler is called.

If a process.stream() handler is set up, then the process.done() handlers will only get any remaining data not consumed by the stream handler.

process.input()

 process.input(data, [stream])

This method writes data to the standard input of the process. If data is null or undefined it is not sent. The data should be a string or an array of bytes if the process was opened in binary mode.

If stream is set to true then this function may be called again with further input. Otherwise the standard input of the process is closed.

process.close()

 process.close([problem])

Close the process. If problem is specified it should be a standard problem code string. In this case the process will be terminated with a signal.

Problem Codes

Cockpit represents problems with standardized problem string codes.

"access-denied"

The user is not permitted to perform the action in question.

"authentication-failed"

User authentication failed.

"internal-error"

An unexpected internal error without further info. This should not happen during the normal course of operations.

"no-cockpit"

The system does not have a compatible version of Cockpit installed or installed properly.

"no-session"

Cockpit is not logged in.

"not-found"

Something specifically requested was not found, such as a file, executable etc.

"terminated"

Something was terminated forcibly, such as a connection, process session, etc.

"timeout"

Something timed out.

"unknown-hostkey"

The remote host had an unexpected or unknown key.

"no-forwarding"

Could not forward authentication credentials to the remote host.

cockpit.message()

 message = cockpit.message(problem)
 message = cockpit.message(exception)

Return a message for the exception or problem code passed as an argument. If the argument is an object with a "message" property, as is the case with most exceptions, that will be returned directly. If the argument is an object with a "problem" property, then it will be used as the problem code. An appropriate message will be returned for problem codes.

DBus Access

Cockpit allows access to DBus services via this API.

DBus values are represented as javascript values and objects as follows:

BYTE 'y'

Javascript number.

BOOLEAN 'b'

Javascript boolean.

INT16 'n'

Javascript number.

UINT16 'q'

Javascript number.

INT32 'i'

Javascript number.

UINT32 'u'

Javascript number.

INT64 'x'

Javascript number.

UINT64 't'

Javascript number.

DOUBLE 'd'

Javascript number.

STRING 's'

Javascript string.

OBJECT_PATH 'o'

Javascript string.

SIGNATURE 'g'

Javascript string.

ARRAY of BYTE 'ay'

A string containing base64 encoded data.

ARRAY of DICT_ENTRY with STRING keys 'a{s?}'

A javascript plain object with the keys as property names.

ARRAY of DICT_ENTRY with other keys 'a{??}'

A javascript plain object each key JSON encoded into a string property name.

ARRAY of other

A javascript array.

VARIANT

A javascript plain object with the "t" property set to a DBus type string, and the "v" property set to a value.

cockpit.dbus()

 client = cockpit.dbus(name, [options])

Create a DBus client for the given bus name (eg: service name). Use the following functions to make DBus method calls, watch for events, etc. The optional options argument is a javascript plain object, and may include:

"bus"

The DBus bus to connect to. Specifying "session" will connect to the DBus user session bus, "user" will connect to the user bus (on some systems this is identical to the session bus), and "system" will connect to the DBus system bus. This defaults to "system" if not present.

"host"

The host to open the channel to. If no host is specified then the correct one will be automatically selected based on the page calling this function.

"superuser"

Try to become root before talking to this service. The DBus service will see the DBus method calls and accesses as coming from root, rather than the logged in user. This is useful for talking to services that do not correctly use polkit to authorize administrative users. If the currently logged in user is not permitted to become root (eg: via pkexec) then the client will immediately be closed with a "access-denied" problem code.

"track"

It is valid for a DBus service to exit, and be restarted in such a way that clients continue to talk to it across the restart. Some services are not written with this in mind. If the "track" option is set to true then the channel will close when the service exits and/or disconnects from the DBus bus.

client.close()

 client.close([problem])

Close the DBus client. If problem is specified it should be a problem code string.

client.onclose

 $(client).on("close", function(options) { ... })

An event triggered when the DBus client closes. This can happen either because client.close() function was called, or the DBus service went away, or some other problem or disconnection.

The options will contain various close information, including a "problem" field which will be set if the channel was closed because of a problem.

client.options

Set to the options used when creating the client. Will not change for the life of the client.

client.proxy

 proxy = client.proxy([interface, path])

Create proxy javascript object for a DBus interface. At the specified DBus object path. The proxy will have properties, methods and signals from to the DBus interface, and allows for natural interaction. If no interface is specified then the DBus bus name of the client is used. If no path is specified, then the DBus name of the client is converted to a path.

If creating lots of proxies for a given interface it is more efficient to use the client.proxies() function.

The proxy is loaded when the proxy.valid field is true, and it is set to false if the underlying interface and/or path don't or no longer exist, or the client has closed. You can wait for proxy to become valid by passing a callback to its proxy.wait() function. The proxy.onchanged event will also fire when the proxy becomes valid or invalid. DBus properties and methods on the proxy are not defined until the proxy becomes valid.

 value = proxy.Prop1
 proxy.WritableProp = value

All DBus properties on the interface that start with an upper case letter (as is convention) will be automatically defined on this proxy, and will update their values as the DBus property values change. In addition the proxy.onchanged event will fire every time the properties change.

If you assign a value to a writable property on the proxy, the proxy will try to set that property on the DBus interface at path. The actual proxy property value will not update until the DBus service has notified the proxy of the change. If setting a property fails a warning will be logged. In order to have more reliable setting of properties, or track when they have been set, or if setting fails, use the client.call() directly. It should be noted that DBus service implementations may also be inconsistent in their behavior when setting a property fails.

You can access the raw property data using the proxy.data field, including data for properties that do not start with an upper case letter.

  proxy.Method(arg1, arg2)
     .done(function(retval1, retval2) {
        ...
     })
     .fail(function(ex) {
        ...
     });

All DBus methods on the interface that start with an upper case letter (as is convention) will be automatically defined on this proxy. These methods are called with arguments as normal javascript arguments. A jQuery promise that will complete sucessfully when the method returns, or fail if an error occurs. The return values from the DBus method will be passed to the done handler function directly.

Methods that do not start with an upper case letter can be invoked by using the usual proxy.call() directly.

  $(proxy).on("Signal", function(event, arg1, arg2) {
      ...
  }(;

All DBus signals on the interface that start with an upper case letter (as is convention) will be automatically emit events on this proxy. These events will contain the signal arguments after the standard event argument.

Signals that do not start with an upper case letter can be subscribed to by using proxy.onsignal directly.

proxy.client

Set to the DBus client of the proxy. Will not change for the life of the proxy.

proxy.path

Set to the DBus object path of the proxy. Will not change for the life of the proxy.

proxy.iface

Set to the DBus interface name of the proxy. Will not change for the life of the proxy.

proxy.valid

Set to true when the proxy's DBus interface is present at its DBus path, and all information for the proxy has loaded. Is set to false while loading, and after the proxy no longer refers a DBus interface and path. Also set to false if the client closes.

Use the by proxy.wait() function to wait for a proxy to load. The proxy.onchanged event will also be emitted when the proxy becomes valid or invalid. DBus properties and methods on the proxy are not defined until the proxy becomes valid.

proxy.data

A plain javascript object containing all the raw property data that this proxy has loaded. This will be updated automatically as the proxy is notified of property changes from the DBus service. The proxy.onchanged event will be emitted when it changes.

proxy.call()

 invocation = proxy.call(method, args, [options])

Make a DBus method call on this proxy.

For DBus methods that start with an upper case letter, is usually more convenient to call the method directly on the proxy. However if methods that do not follow the usual DBus convention, or specify additional options, or the caller cannot be sure that the method actually exists, you can use this method.

This function also works on proxies that have are still loading and have not become valid yet.

The method should be a DBus method name, and the args should be an array of arguments to pass to the method. The options are described elsewhere.

The returned value is identical to the one returned from client.call(). It is a jQuery promise that will complete sucessfully when the method returns, or fail if an error occurs.

proxy.wait()

 proxy.wait(function() {
   ...
 });

Wait for a proxy to finish loading, and invoke the callback function when ready. If this method is called after a proxy has already loaded, then the callback will be invoked immediately. Use proxy.valid to determine whether the proxy loading resulting in a valid proxy.

proxy.onchanged

 $(proxy).on("changed", function(data) {
   ...
 });

This event is emitted when the proxy's properties change.

The data has the following form, and will only include properties that have changed:

  {
    "Prop1": "value",
    "Prop2": 5
  }

proxy.onsignal

 $(proxy).on("signal", function(event, name, args) {
   ...
 });

This event is emitted when the proxy's emits an event.

For most events, that have names which start with an upper case letter, you can just connect to that event as a signal directly. However if you wish to be notified when any signal is emitted, or for signals that do not follow the usual DBus convention, you can connect to this event.

The name is the DBus signal name, and the args is an array of arguments that were emitted with the signal.

client.proxies

  proxies = client.proxies([interface], [path_namespace])

Create proxy javascript objects for a DBus interfaces. The proxes will have properties, methods and signals from the DBus interface, and allow for natural interaction. If no interface is specified then the DBus bus name of the client is used. If no path_namespace is provided then "/" will be used.

Proxies will be automatically created for instances of the interface available at the DBus service. The optional path_namespace argument can be used to restrict the proxies for instances that have DBus paths which have the namespace path prefix.

  proxy1 = proxies["/dbus/path1"];
  proxy2 = proxies["/dbus/path2"];
  for (proxy in proxies) {
    ...
  }

The returned proxies object will is used as a dictionary, and will have values containing proxies for DBus interface instances, with the keys being the DBus paths of those instances. It is possible to enumerate over the returned proxies.

Proxies will be automatically added and removed from the proxies object as they appear and disappear in the service. The proxies.onadded and proxies.onremoved events will be emitted. DBus services may not support notifications of paths disappearing.

Use the proxies.wait() function to be notified when the initial set of proxies has been populated.

proxies.wait()

 proxies.wait(function() {
   ...
 });

Wait for a proxies object to populate its initial set of proxies. If this method is called after the proxies have populated, the callback will be invoked immediately.

proxies.client

Set to the DBus client of the proxies. Will not change.

proxies.iface

Set to the DBus interface name of the proxies. Will not change.

proxies.path_namespace

Set to the DBus path namespace used which the proxies must have as a DBus path prefix. Will not change.

proxies.onadded

 $(proxies).on("added", function(event, proxy) {
   ...
 })

This event is emitted when a proxy is added to the proxies object. The proxy will already have loaded.

proxies.onchanged

 $(proxies).on("changed", function(event, proxy) {
   ...
 })

This event is emitted when one of the proxy in the proxies object changes its properties.

proxies.onremoved

 $(proxies).on("removed", function(event, proxy) {
   ...
 })

This event is emitted when a proxy is removed to the proxies object.

client.call()

  invocation = client.call(path, interface, method, args, [options])

Make a DBus method call.

The path is the DBus object path to make the call on, interface is the DBus interface for the method and method is the name of the method to call. The args is an array of arguments to pass to the method, each of which must be appropriate for the expected DBus type of that argument. The args may be null if no arguments are to be sent.

The returned value is a jQuery promise that will complete sucessfully when the method returns, or fail if an error occurs.

If options is specified it should be a plain javascript object, which may contain the following properties:

flags

A string containing DBus message flags. No flags are defined at this time.

type

A valid DBus type signature to use when calling the method. In the absence of this, the DBus service will be introspected (and the result cached) to ask what the method type signature is.

invocation.done()

 invocation.done(function(args, options) { ... })

This is a standard jQuery promise method. It sets up a handler to be called when the DBus method call finishes successfully.

The args argument is an array of return values from the DBus method. Each of them will be converted to an appropriate javascript type.

The options argument may contain additional information about the reply. If the type option was specified when performing the method call, then the options in the reply here will also contain a type field containing the DBus type signature of the output. If the flags option was specified when performing the call then the options in the reply here will contain message flags. Possible out message flags are:

>

A big endian message.

<

A little endian message.

invocation.fail()

 invocation.fail(function(exception) { ... })

This is a standard jQuery promise method. It sets up a handler to be called when the DBus method call fails.

The exception object passed to the handler can have the following properties:

problem

A problem code string when a problem occurred starting or communicating with the DBus service. This is null in the cases where an actual DBus error was occurred.

name

The DBus error name. This will be null in cases where the failure was not due to a DBus error.

message

A DBus error message. This will be null in cases where the failure was not due to a DBus error.

invocation.always()

 invocation.always(function() { ... })

This is a standard jQuery promise method. It sets up a handler to be called when when the DBus method call finishes whether successfully, or fails.

client.subscribe()

 subscription = client.subscribe(match, function(path, interface, signal, args) { ... })

Subscribe to signals. The match argument is a javascript plain object which defines what signals to subscribe to. Each property in the match argument restricts signals subscribed to. If a property is not present then it is treated as a wildcard, matching anything. If an empty object is specified as match then all signals will be subscribed to. The match argument may contain the following properties:

interface

A DBus interface to match.

path

A DBus object path to match. May not be used together with the path_namespace property. It should be a valid DBus object path, that is, it should have no trailing slash.

path_namespace

A DBus object path prefix to match. Any paths in the hierarchy below this top path will match. May not be used together with the path property.

member

The DBus signal name to match.

arg0

Matches the first argument of a DBus message, which must be a string.

The handler passed as the second argument will be invoked when the signal is received. A subscription is returned which can be used to remove the subscription by calling its subscription.remove() method.

It is not a problem to subscribe to the same signals more than once, with identical or slightly different match arguments.

subscription.remove()

 subscription.remove()

Unsubscribe from the DBus signal subscription.

client.watch

 watch = client.watch(path)
 watch = client.watch({ "path_namespace": path_namespace, "interface": interface })

Watch for property and interface changes on the given DBus object path DBus path_namespace. If interface is specified only properties on that DBus interface will be watched.

The client.proxy() and client.proxies() functions and the objects they return are high level wrappers around client.watch().

The property and interface changes will be available in raw form on the client.onnotify event.

Property and interface changes that are caused by a method call or signal will show up before that method call reply is received, or signal event is triggered. It should be possible to rely on this guarantee, unless the DBus service in question behaves incorrectly. Internally these watches work well with code that implements the ObjectManager portion of the DBus specification. If no ObjectManager implementation is available, the watch falls back to using DBus Introspection along with the usual PropertiesChanged signal. If the DBus service implements none of these, or implements them in an inconsistent manner, then this function will provide inconsistent or unexpected results.

The parameter is either a DBus path or a plain javascript object with zero or more of the following fields. If an empty javascript object is used as an argument, then all paths, interfaces and properties will be watched.

interface

Watch properties on this DBus interface.

path

Watch interfaces and properties at this DBus path. May not be used together with the path_namespace property.

path_namespace

Watch interfaces and properties under this DBus path. It should be a valid DBus object path, that is, it should have no trailing slash. If an ObjectManager implementation is available at this interface, then it is used. May not be used together with the path property.

The returned value is a jQuery promise that will complete sucessfully when the watch has populated its initial set of properties and interfaces, and these have been notified via client.onnotify.

A watch can be removed by calling the watch.remove() method on the returned value. If identical watches are added more than once, then they must also be removed the same number of times before the removal takes effect.

watch.done()

 watch.done(function() { ... })

This is a standard jQuery promise method. It sets up a handler to be called when the watch has populated its initial properties and interfaces.

watch.fail()

 watch.fail(function() { ... })

This is a standard jQuery promise method. It sets up a handler to be called if the watch fails to populate its initial properties and interfaces. Note that a watch will only fail if the DBus client closes or is somehow disconnected. It does not fail in the case of missing interfaces or properties.

watch.always()

 watch.always(function() { ... })

This is a standard jQuery promise method. It sets up a handler to be called when the watch has populated its initial properties and interfaces or has failed to do so.

watch.remove()

 watch.remove()

Remove the watch. This may not have any immediate effect if other watches are in place. In particular, if identical watches are added more than once, then they must also be removed the same number of times before the removal takes effect.

client.onnotify

 $(client).on("notify", function(data) { ... })

An event triggered when watched properties or interfaces change.

The client.proxy() and client.proxies() functions and the objects they return are high level wrappers around the data provided by this event.

The data has the following form:

  {
      "/path1": {
         "org.Interface1": {
            "Prop1": "value",
            "Prop2": 5
         },
         "org.Interface2": null
      }
  }

Multiple paths may be present, each of which may have multiple interfaces, each of which may have multiple properties. The first time a given path and interface is emitted from this signal, it will have all its properties and interfaces. Thereafter only changes are noted. If an interface is set to null, then that interface has disappeared.

client.notify

  client.notify(data)

Emits a synthetic notify event. The data argument should follow the same layout as described for the notify event.

cockpit.variant()

 variant = cockpit.variant(type, value)

A DBus variant is represented as a plain javascript object with a "t" property represesting the full DBus type of the variant, and a "v" property containting the variant value.

This is a helper function for creating such a variant object.

cockpit.byte_array()

 byte_array = cockpit.byte_array(value)

A DBus byte array is represnted as base64 data encoded in a string. This is a helper function for creating such a byte array.

HTTP Access

Cockpit allows access to local HTTP and REST services via this API.

This is not a general purpose HTTP request API. In particular in only accesses unix sockets and localhost ports on the server. Use your browser's XmlHttpRequest API for other more general HTTP access.

cockpit.http()

 http = cockpit.http(endpoint, [options])
 http = cockpit.http(options)

Create a new HTTP client. The endpoint can be a file path starting with / to connect to a unix socket, or it can be a port number to connect to on localhost.

"connection"

A connection identifier. Subsequent channel requests with the same identifier will try to use the same connection if it is still open.

"superuser"

Try to open this channel as root. If the currently logged in user is not permitted to become root (eg: via pkexec) then the channel will immediately be closed with a "access-denied" problem code.

http.get()

  request = http.get(path, [params, [headers]])

Perform an HTTP GET request for the given path. If the params is specified it should be a plain javascript object, which will be turned into a query string.

Optionally a plain javascript object containing headers can be included in the headers argument.

The return value is a jQuery promise that will complete if the request happens successfully, or fail if there's a problem.

http.post()

  request = http.post(path, body, [headers])

Perform an HTTP POST request for the given path. The body can be a string, or a javascript plain object, which will be encoded as JSON data. If body is undefined or null then an empty HTTP body will be sent.

Optionally a plain javascript object containing headers can be included in the headers argument.

The return value is a jQuery promise that will complete if the request happens successfully, or fail if there's a problem.

http.request()

  request = http.request(options)

Perform an HTTP request. The options can contain the following:

"body"

The HTTP request body. If you do not specify a body, then you must call request.input() to complete the body and allow the request to start.

"headers"

A javascript plain object containing HTTP headers.

"method"

The HTTP method. Defaults to "GET".

"params"

A javascript plain object containing query string parameters.

"path"

The HTTP path. Defaults to /.

The return value is a jQuery promise that will complete if the request happens successfully, or fail if there's a problem.

request.done()

 request.done(function(data) { ... })

This is a standard jQuery promise method. It sets up a handler to be called when the request finishes successfully.

The data argument contains the body result of the request. If it a string, unless the process was opened in binary mode, in which case the data is an array of bytes. If a request.stream() handler is set up, then any standard output data consumed by the handler will not be included in the data argument.

request.fail()

 request.fail(function(exception[, data]) { ... })

This is a standard jQuery promise method. It sets up a handler to be called when the request fails, or returns an error code.

The exception object passed to the handler can have the following fields:

problem

A problem code string when a problem occurred starting or communicating with the server. This is null if the process exited or was terminated.

status

The numeric status of the response. This is null if no response was received.

reason

A string reason returned in the response. This is null if no response was received.

message

A string message returned in the response. This is null if no response was received.

If the request returned a response body, it will be available in the data argument. Otherwise this argument will be undefined.

request.always()

 request.always(function() { ... })

This is a standard jQuery promise method. It sets up a handler to be called when when the process completes, whether it exits successfully, fails, terminates, or exits with a failure.

request.response()

 request.response(function(status, headers) { ... })

This sets up a handler to be called when the HTTP request gets the initial response from the server. The status argument is the HTTP status integer, and the headers is a plain javascript object containing the headers of the response.

request.stream()

 request.stream(function(data) { ... })

This sets up a handler to be called when the request returns output data. The handler will be called multiple times.

Only one handler may be registered at a time. Registering an additional handler replaces the previous one. The handler receives either string data or an array of binary bytes as its argument. A stream handler may return a number, which indicates the number of characters or bytes consumed from data. Any data not consumed will be included again the next time the handler is called.

If a request.stream() handler is set up, then the request.done() handlers will only get any remaining data not consumed by the stream handler.

request.input()

 request.input(data, [stream])

This method writes data to the HTTP request body. It is only valid if no "body" has been specified in http.request() options. If stream is true then this function can be called again to provide further data.

request.close()

 request.close([problem])

Cancel the request. If problem is specified it should be a standard problem code string.

Permission Lookup

Cockpit provides a mechanism for checking if the current user satisfies a given criteria. Currently capable of checking for root users, and group membership. This is meant for updating UI elements based on what actions the user can perform. It is not an access control mechanism.

cockpit.permission()

 permission = cockpit.permission([options])

Create a new permission object to check if the current user has permission. The "root" user is always given permission. The options argument can contain a "group" field, and members of that group are also given permission.

permission.allowed

A boolean value which indicates if the permission is allowed or not. This will be null if the permission is unknown, or there was an error checking the permission or the the permission data has not yet loaded. This property will update asynchronously and if you wish to be notified of changes connect to the permission.onchanged event.

permission.onchanged

  $(permission).on("changed", function() { ... })

This event is fired when the permission changes. In particular the permission.allowed property.

permission.close()

  permission.close()

Closes the permission object and tears down any registered callbacks and dbus subscriptions.

Localization

Cockpit provides a gettext() like API for easy translation of strings.

cockpit.language

The current locale language code. This is set based on the cockpit.locale() data loaded.

cockpit.locale()

 cockpit.locale(po)

Load locale information for a given po data. The data should be JSON data in the po2json format. The data will be loaded globally. If po data has already been loaded, then this will extend that loaded data with additional strings. Any identical translations strings will be replaced with the new strings.

Various methods such as cockpit.gettext() make use of the loaded data.

cockpit.gettext()

 translated = cockpit.gettext([context], string)
 var _ = cockpit.gettext
 var C_ = cockpit.gettext
 translated = _("string")
 translated = C_("context", "string")

Lookup string for translation in the loaded locale data. The translated string will be returned, or string will be returned if no such translated string is present. The context argument is an optional string used to qualify the string.

This function can be assigned to a variable called _ (underscore) which will make your code work with the typical _("string") syntax.

cockpit.noop()

  var N_ = cockpit.noop
  var NC_ = cockpit.noop

A noop function suitable for assigning to N_ or NC_ so that gettext scanners will be able to find translatable strings. More specifically this function returns its last argument.

cockpit.ngettext()

 translated = cockpit.ngettext([context], string1, stringN, number)

Lookup a string appropriate for a pluralization form of the number. Various languages have complex pluralization forms that go far between the singular and plural forms speakers of English are familiar with. If no such translated string is found then either one of string1 or stringN is returned according to simple pluralization rules.

The context argument is an optional string used to qualify the string.

cockpit.translate()

 cockpit.translate([sel])

The document will be scanned for translatable tags and they will be translated according to the strings in loaded locale data. If sel is specified, this should be a jQuery selector for the specific part of the document to translate.

File Access

Reading, writing, and watching files.

file = cockpit.file(path,
                    { syntax: syntax_object,
                      binary: boolean
                    })

promise = file.read()
promise
    .done(function (content, tag) { ... })
    .fail(function (error) { ... })

promise = file.replace(content, [ expected_tag ])
promise
    .done(function (new_tag) { ... })
    .fail(function (error) { ... })

promise = file.modify(callback, [ initial_content, initial_tag ]
promise
    .done(function (new_content, new_tag) { ... })
    .fail(function (error) { ... })

file.watch(function (content, tag, [error]) { })

file.close()

Simple reading and writing

You can read a file with code like this:

cockpit.file("/path/to/file").read().
    done(function (content, tag) {
        ...
    }).
    fail(function (error) {
        ...
    });

The read() method returns a jQuery promise.

When successful, the promise will be resolved with the content of the file. Unless you specify options to change this (see below), the file is assumed to be text in the UTF-8 encoding, and content will be a string.

The tag that is passed to the done() callback is a short string that is associated with the file and changes whenever the content of the file changes. It is meant to be used with replace().

It is not an error when the file does not exist. In this case, the done() callback will be called with a null value for content and tag is "-".

To write to a file, use code like this:

cockpit.file("/path/to/file").replace("my new content\n").
    done(function (tag) {
        ...
    }).
    fail(function (error) {
        ...
    });

The replace() method returns a jQuery promise.

When the promise is resolved, the file has been atomically replaced (via the rename() syscall) with the new content. As with read(), by default the new content is a string and will be written to the file as UTF-8. The returned tag corresponds to the new content of the file.

When the promise is rejected because of an error, the file or its meta data has not been changed in any way.

As a special case, passing the value null to replace() will remove the file.

The replace() method can also check for conflicting changes to a file. You can pass a tag (as returned by read() or replace()) to replace(), and the file will only be replaced if it still has the given tag. If the tag of the file has changed, replace() will fail with an error object that has error.problem == "change-conflict". See modify() below for a convenient way to achieve transactional updates to a file.

File format

By default, a file is assumed to be text encoded in UTF-8, and the read() and replace() functions use strings to represent the content.

By specifying the syntax.parser() and syntax.stringify() options, you can cause read() to parse the content before passing it back to you, and replace() to unparse it before writing.

The main idea is to be able to write { syntax: JSON }, of course, but you can easily pass in individual functions or make your own parser/unparser object:

cockpit.file("/path/to/file.json", { syntax: JSON })

var syntax_object = { parse:     my_parser,
                      stringify: my_unparser
                    };

cockpit.file("/path/to/file", { syntax: syntax_object })

Any exceptions thrown by the parse() and stringify() functions are caught and reported as read or write errors.

The null value that is used to represent the content of a non-existing file (see "Simple reading and writing", above) is not passed through the parse() and stringify() functions.

Binary files

By default the content of the file is assumed to be text encoded as UTF-8 and it can not contain zero bytes. The content is represented as a JavaScript string with read(), replace(), etc. By setting the binary option to true when creating the proxy, no assumptions are placed on the content, and it is represented as a Uint8Array in JavaScript.

Atomic modifications

Use modify() to modify the content of the file safely. A call to modify() will read the content of the file, call callback on the content, and then replace the content of the file with the return value of the callback.

The modify() method uses the read() and replace() methods internally in the obvious way. Thus, the syntax.parse() and syntax.stringify() options work as expected, null represents a non-existing file, and the watch callbacks are fired.

It will do this one or more times, until no other conflicting changes have been made to the file between reading and replacing it.

The callback is called like this

    new_content = callback (old_content)

The callback is allowed to mutate old_content, but note that this will also mutate the objects that are passed to the watch callbacks. Returning undefined from the proxy is the same as returning old_content.

The modify() method returns a jQuery promise.

The promise will be resolved with the new content and its tag, like so

function shout(old_content) {
   return old_content.toUpperCase();
}

cockpit.file("/path/to/file").modify(shout).
    done(function (content, tag) {
        ...
    }).
    fail(function (error) {
        ...
    });

If you have cached the last content and tag results of the read() or modify() method, or the last values passed to a watch callback, you can pass them to modify() as the second and third argument. In this case, modify() will skip the initial read and start with the given values.

Change notifications

Calling watch() will start monitoring the file for external changes.

handle = file.watch(callback);

Whenever a change occurs, the callback() is called with the new content and tag of the file. This might happen because of external changes, but also as part of calls to read(), replace(), and modify().

When a read error occurs, the callback() is called with an error as a third argument. Write errors are not reported via the watch callback.

Calling watch() will also automatically call read() to get the initial content of the file.

Thus, you normally don't need to call read() at all when using watch().

To free the resources used for monitoring, call handle.remove().

Closing

Call the close() method on a file proxy to cancel all ongoing operations, such as reading, writing, and monitoring. The proxy should not be used after closing it.

Utilities

Various utility functions.

cockpit.format()

 string = cockpit.format(template, args)
 string = cockpit.format(template, [arg, ...])

Format a string interpolating args into template using shell like syntax. The args may be either an array or javascript object. The template can contain fields that look like $name or ${name} or $0. Numeric fields are used with array args and start at zero.

In the second form, multiple arg arguments may be passed directly, and interpolated as as numeric fields in the template.

cockpit.format_bytes()

 string = cockpit.format_bytes(number, [factor])
 array = cockpit.format_bytes(number, [factor, separate])

Formats number into a displayable string with a suffix, such as KB or MB. Returns an array of the formatted number and the suffix if separate is set to true.

If specifying 1000 or 1024 is specified as a factor then an appropriate suffix will be chosen. By default the factor is 1024. You can pass a string suffix as a factor in which case the resulting number will be formatted with the same suffix.

If the number is less than the factor or an unknown factor was passed in, then the formatted number is returned without a suffix. If separate is true, returns an array of [formatted_number, suffix] unless no suffix is returned.

cockpit.format_bytes_per_sec()

   string = cockpit.format_bytes_per_sec(number)
  

Format number of bytes into a displayable speed string.

cockpit.format_bits_per_sec()

    string = cockpit.format_bits_per_sec(number)
  

Format number of bits into a displayable speed string.

Manifest Info

You can load manifest info by loading the ./manifest.json file in your package. In addition there is a shortcut: if you're using AMD loading you can use a special module id to access all the manifests in one shot:

  define([
      'manifests',
      'other.dep'
  ], function(manifests, other) {
    var manifest = manifests['package'];
  });

Raw Channels

At a low level Cockpit communicates with the system via messages passed through various channels. These are usually exposed via higher level APIs, such as the cockpit.spawn() function. It is rare to use raw channels directly.

cockpit.channel()

 channel = cockpit.channel(options)

This function creates a new channel for communication with the system. It returns a new channel object. The options argument is a plain object. At least the "payload" option is required, and based on the payload type, other options may be required.

"binary"

Set to true to transfer binary payloads. Both messages sent via channel.send() and those received via channel.onmessage should be arrays of bytes, either Uint8Array or Array depending on browser support.

"host"

The host to open the channel to. If no host is specified then the correct one will be automatically selected based on the page calling this function.

"payload"

The payload type for the channel. Only specific payload types are supported.

"superuser"

Try to open this channel as root. If the currently logged in user is not permitted to become root (eg: via pkexec) then the channel will immediately be closed with a "access-denied" problem code.

The channel object returned has the following fields and methods and events. You should call the channel.close() method when done with the channel.

A valid channel will always be returned and the is ready to channel.send(). The channel may close shortly afterword due to a failure.

channel.binary

Will be true for an binary channel. Will be set to false if the channel is textual.

channel.options

The options used to open this channel. This should not be changed.

channel.valid

Will be true for an open channel. Will be set to false if the channel closes.

channel.send()

 channel.send(data)

Send a message over the channel. The contents of the message depends on the payload type of the channel. If a binary channel, then data is expected to be an Array of bytes or a Uint8Array. If not binary, then the data will be converted to a string if not already a string.

channel.control()

 channel.control(options)

Notify the channel to tune certain parameters on the fly. The options is a plain javascript object, and the contents depend on the "payload" of the channel.

One common operation is to set "command" to "done" in the options field. To indicate that no further messages will be sent through the channel.

channel.close()

 channel.close([options])

Close the channel.

If options is present it can be a plain javascript object containing additional channel close options to send to the peer. If closing for because of a problem, set the "problem" field to a problem code. If options is not an object it will be treated as a "problem".

The close event will fire. A channel can also be closed by a peer or if the underlying transport closes.

channel.onmessage

 $(channel).on("message", function(event, data) { ... })
 channel.addEventListener("message", function(event, data) { ... })

An event triggered when the channel receives a message. The message is passed as a string to the handler in the data. In the case of binary channels data is an Uint8Array or an Array of bytes if the former is not supported by the browser. The contents of the message depends on the payload type of the channel.

channel.oncontrol

 $(channel).on("control", function(event, options) { ... })
 channel.addEventListener("control", function(event, options) { ... })

An event triggered when the channel receives an control message in the middle of the flow. One particular use is when the command is set to "done" then no further messages will be received in the channel. The exact form of these messages depend on the "payload" of the channel.

channel.onclose

 $(channel).on("close", function(options) { ... })
 channel.addEventListener("close", function(event, options) { ... })

An event triggered when the channel closes. This can happen either because channel.close() function was called, or if the peer closed the channel, or the underlying transport closes.

The options will contain various close information, including a "problem" field which will be set if the channel was closed because of a problem.

cockpit.transport.origin

  cockpit.transport.origin

The HTTP origin that is being used by the underlying channel transport. This is read-only, you should not assign a value. If the browser supports window.location.origin then this will be identical to that value.

cockpit.transport.host

  cockpit.transport.host

The host that this transport is going to talk to by default. This is read-only, you should not assign a value. If the value is null that means that the transport has not been setup yet.

cockpit.transport.options

  cockpit.transport.options

Initialization options received over the underlying channel transport. These will be empty until connection is properly established.

cockpit.transport.close()

  cockpit.transport.close([problem])

Close the underlying channel transport. All channels open channels will close. The problem argument should be a problem code string. If not specified it will default to "disconnected".

cockpit.transport.filter()

  cockpit.transport.filter(function(message, channel, control) { ... })

Add a filter to the underlying channel transport. All incoming messages will be passed to each of the filter callbacks that are registered.

This function is rarely used.

Filter callbacks are called in the order they are registered. If a filter callback returns false then the message will not be dispatched further, whether to other filters, or to channels, etc.

The message is the string or array with the raw message including, the framing. If channel is set to a string this is a payload message in the specified channel. If control is set then this is a control message, and the control argument contains the parsed JSON object of the control message.

cockpit.transport.inject()

  cockpit.transport.inject(message)

Inject a message into the underlying channel transport. The message should be a string or an array of bytes, and should be valid according to the Cockpit message protocol.

This function is rarely used. In general you should only inject() messages you got from a filter().

cockpit.base64_encode()

  string = cockpit.base64_encode(data)

Encode binary data into a string using the Base64 encoding. The data argument can either be a string, an Array, an ArrayBuffer or a Uint8Array. The return value is a string.

cockpit.base64_decode()

  data = cockpit.base64_decode(string, [constructor])

Decode binary data from a Base64 encoded string. The string argument should be a javascript string. The returned data> will be an array of bytes.

You can pass Uint8Array, Array or String as an alternate contstructor if you want the decoded data in an alternate form. The default is to return an Array. Note that if you use a String for the decoded data, then you must guarantee that the data does not contain bytes that would be invalid for a string.

cockpit.utf8_encoder()

  encoder = cockpit.utf8_encoder([constructor])

Create an encoder for encoding a string into a UTF8 sequence of bytes.

You can pass Uint8Array, Array or String as an alternate contstructor if you want the decoded data in an alternate form. The default is to return an Array.

encoder.encode()

  data = encoder.encode(string)

Encode a string into a UTF8 sequence of bytes.

The resulting data is an array of bytes, but it's type may be modified by passing an alternate constructor to cockpit.utf8_encoder().

cockpit.utf8_decoder()

  decoder = cockpit.utf8_decoder([fatal])

Creates a decodker to decode a UTF8 sequence of bytes data into a string.

If the fatal is set to true then the decoder will throw an exception when it encounters invalid UTF8 data. By default invalid data will be substituted with special UTF8 characters.

decoder.decode()

  string = decoder.decode(data, [options])

Decode an array of UTF8 bytes into a string. The data argument may be an Array, a Uint8Array or a string containing binary data.

If options is passed it should be a plain javascript object. If options has a stream property equal to true, then multiple invocations of this function can be made with parts of the UTF8 sequence of bytes. Any trailing bytes that don't yet build a complete unicode character, will be cached until the next invocation. To drain the last data, call this function without the stream property set.

Cockpit Version Info

cockpit.info

  cockpit.info["version"]
  cockpit.info["build"]

This object contains information about cockpit itself. Note that when cockpit is running on multiple servers, this only reflects the server that was connected to. The following fields are defined:

"build"

A string containing build details.

"version"

A string containing the cockpit version number. It is almost always incorrect to use this to make a decision in code.