remove some old documentation, relocate others (#4726)

* remove some old documentation, relocate others

* small tweak to default config
This commit is contained in:
Darren Schroeder
2022-03-04 10:37:08 -06:00
committed by GitHub
parent e64ca97fe2
commit b714e034aa
12 changed files with 5 additions and 1315 deletions

141
docs/old/docker.md Normal file
View File

@ -0,0 +1,141 @@
# Docker Guide
| tag | base image | plugins | package manager | libs & bins | size |
| ------------------ | -------------------- | ------- | --------------- | ---------------------------------------------------------------- | ----------- |
| `latest`, `debian` | `debian:latest` | yes | apt | **a lot**, including _glibc_ | ~(48+62) MB |
| `slim` | `debian:stable-slim` | yes | apt | all `nu:debian` image but exclude [this list][.slimify-excludes] | ~(26+62) MB |
| `alpine` | `alpine:latest` | yes | apk | all `nu:musl-busybox` image + libcrypto, libssl, libtls, libz | ~(3+61) MB |
| `musl-busybox` | `busybox:musl` | no | — | GNU utils + _musl_ | ~(1+16) MB |
| `glibc-busybox` | `busybox:glibc` | no | — | GNU utils + _glibc_ | ~(3+17) MB |
| `musl-distroless` | `distroless/static` | no | — | see [here][distroless/base] | ~(2+16) MB |
| `glibc-distroless` | `distroless/cc` | no | — | `distroless/static` with _glibc_ | ~(17+17) MB |
| `glibc` | `scratch` | no | — | **only `nu` binary-executable** which depend on glibc runtime | ~17 MB |
| `musl` | `scratch` | no | — | **only `nu` binary-executable** statically linked to musl | ~16 MB |
[.slimify-excludes]: https://github.com/debuerreotype/debuerreotype/blob/master/scripts/.slimify-excludes
[distroless/base]: https://github.com/GoogleContainerTools/distroless/blob/master/base/README.md
## Image Variants
### `nu:<version>`
This is the defacto image. If you are unsure about what your needs are, you probably want to use this one. It is designed to be used both as a throw away container (mount your source code and start the container to start your app), as well as the base to build other images off of.
<details><summary>example</summary>
Let say you create a plugin in Rust.
- create a Dockerfile in your root project
```dockerfile
FROM nu:0.2
COPY /target/debug/nu_plugin_cowsay /bin/
ENTRYPOINT ["nu"]
```
- build your project first then run it via docker
```bash
cargo build
docker run -it .
```
</details>
### `nu:<version>-slim`
This image does not contain the common packages contained in the default tag and only contains the minimal packages needed to run `nu`. Unless you are working in an environment where only the `nu` image will be deployed and you have space constraints, it's highly recommended to use the alpine image if you aim for small image size. Only use this image if you really need **both** `glibc` and small image size.
### `nu:<version>-alpine`
This image is based on the popular [Alpine Linux project](https://alpinelinux.org/), available in [the alpine official image][alpine]. Alpine Linux is much smaller than most distribution base images (~5MB), and thus leads to much slimmer images in general.
This variant is highly recommended when final image size being as small as possible is desired. The main caveat to note is that it does use `musl` libc instead of `glibc` and friends, so certain software might run into issues depending on the depth of their libc requirements. However, most software doesn't have an issue with this, so this variant is usually a very safe choice. See [this Hacker News comment thread](https://news.ycombinator.com/item?id=10782897) for more discussion of the issues that might arise and some pro/con comparisons of using Alpine-based images.
To minimize image size, it's uncommon for additional related tools (such as `git` or `bash`) to be included in Alpine-based images. Using this image as a base, add the things you need in your own Dockerfile (see the [alpine image description][alpine] for examples of how to install packages if you are unfamiliar).
### `nu:<version>-<libc-variant>`
This image is based on [`scratch`](https://hub.docker.com/_/scratch) which doesn't create an extra layer. This variants can be handy in a project that uses multiple programming language as you need a lot of tools. By using this in [multi-stage build][], you can slim down the docker image that need to be pulled.
[multi-stage build]: https://docs.docker.com/develop/develop-images/multistage-build/
<details><summary>example</summary>
- using `glibc` variant
```dockerfile
FROM nu:0.2-glibc as shell
FROM node:slim
# Build your plugins
COPY --from=shell /bin/nu /bin/
# Something else
ENTRYPOINT ["nu"]
```
- using `musl` variant
```dockerfile
FROM nu:musl as shell
FROM go:alpine
# Build your plugins
COPY --from=shell /bin/nu /bin/
# Something else
ENTRYPOINT ["nu"]
```
</details>
### `nu:<version>-<libc-variant>-distroless`
This image is base on [Distroless](https://github.com/GoogleContainerTools/distroless) which usually to contain only your application and its runtime dependencies. This image do not contain package managers, shells or any other programs you would expect to find in a standard Linux distribution except for nushell itself. All distroless variant always contains:
- ca-certificates
- A /etc/passwd entry for a root user
- A /tmp directory
- tzdata
As for `glibc-distroless` variant, it **adds**:
- glibc
- libssl
- openssl
> Most likely you want to use this in CI/CD environment for plugins that can be statically compiled.
<details><summary>example</summary>
```dockerfile
FROM nu:musl-distroless
COPY target/x86_64-unknown-linux-musl/release/nu_plugin_* /bin/
ENTRYPOINT ["nu"]
```
</details>
### `nu:<version>-<libc-variant>-busybox`
This image is based on [Busybox](https://www.busybox.net/) which is a very good ingredient to craft space-efficient distributions. It combines tiny versions of many common UNIX utilities into a single small executable. It also provides replacements for most of the utilities you usually find in GNU fileutils, shellutils, etc. The utilities in BusyBox generally have fewer options than their full-featured GNU cousins; however, the options that are included provide the expected functionality and behave very much like their GNU counterparts. Basically, this image provides a fairly complete environment for any small or embedded system.
> Use this only if you need common utilities like `tar`, `awk`, and many more but don't want extra blob like nushell plugins and others.
<details><summary>example</summary>
```dockerfile
FROM nu:0.2-glibc-busybox
ADD https://github.com/user/repo/releases/download/latest/nu_plugin_cowsay.tar.gz /tmp/
RUN tar xzfv nu_plugin_cowsay.tar.gz -C /bin --strip=1 nu_plugin_cowsay
ENTRYPOINT ["nu"]
```
</details>
[musl]: https://www.musl-libc.org/
[alpine]: https://hub.docker.com/_/alpine/

View File

@ -0,0 +1,9 @@
# how to compile without OpenSSL
You may find it desirable to compile nu shell without requiring an OpenSSL installation on your system.
You can do this by running:
```sh
cargo build --no-default-features --features=rustyline-support
```

View File

@ -0,0 +1,39 @@
# How To Port Old Engine Syntax to the Latest and Greatest
## engine-p
Even in the new codebase of nu things change and we have some old code to clean up.
This guide walks you through how to port old engine syntax to engine-p.
1. change into the commands source directory
```sh
cd crates/nu-command/src/
```
2. search for old syntax using ripgrep (`rg`)
```sh
rg --type rust --files-with-matches 'ActionStream|run_with_actions'
```
3. update the old syntax engine-p syntax
- For a smaller example PR see [#3794](https://github.com/nushell/nushell/pull/3794/files)
- For a more involved example PR see [#3649](https://github.com/nushell/nushell/pull/3649/files)
In many cases this is changing the function name and signature.
The function name goes from `run_with_actions` to `run`.
The signature goes from `Result<ActionStream, ShellError>`
to `Result<OutputStream, ShellError>`.
Sometimes you cannot alter the signature because the command
still requires working with `ActionStream`.
[open](https://github.com/nushell/nushell/blob/28db8022fef7c1f7f44f6e50d07d3f42773deddf/crates/nu-command/src/commands/filesystem/open.rs) is one example.
4. commit changes, run the tests, filtered by the command package and section name:
```sh
cargo test --features=extra -p nu-command string
```
5. PR and bask in the glory of the nu-and-improved codebase.

View File

@ -0,0 +1,270 @@
# Implementing a Command
We will be learning how to write a command and see what's required to do so in small steps. For this example we are interested writing a command named `take-two` that takes two lucky values coming in.
Let's generate a table with row literal syntax first, like so:
```
> echo [[repository, LOC]; [nushell, 11161984] [scripts, 500] [nushell_book, 200]]
──────────────┬──────────
repository │ LOC
──────────────┼──────────
nushell │ 11161984
scripts │ 500
nushell_book │ 200
──────────────┴──────────
```
_Note: values are passed around in the stream. A generated table like the example above is three row values. See the [values chapter](https://www.nushell.sh/contributor-book/values.html) to learn more about row value types._
We want to `take-two` rows from the generated table. Here is what we would like to do:
```
> echo [[repository, LOC]; [nushell, 11161984] [scripts, 500] [nushell_book, 200]] | take-two
──────────────┬──────────
repository │ LOC
──────────────┼──────────
nushell │ 11161984
scripts │ 500
──────────────┴──────────
```
See the `take-two` command in the pipeline above? That's what we want.
Before starting writing the command it's important to understand that everything in the stream are values. Sometimes you will see a table with no columns and the reason is that none of the values coming in are row value types. For this case we call it simply a _list_, like so:
```
> echo [[repository, LOC]; [nushell, 11161984] [scripts, 500] [nushell_book, 200]] | get repository
──────────────
nushell
scripts
nushell_book
──────────────
```
The example above Nu sees three values of type String (the call `get repository` returns them).
What happens if the stream has row value types and other value types? Let's find out:
```
> echo [[repository, LOC]; [nushell, 11161984] [scripts, 500] [nushell_book, 200]] | append 10
──────────────┬──────────
repository │ LOC
──────────────┼──────────
nushell │ 11161984
scripts │ 500
nushell_book │ 200
──────────────┴──────────
────
10
────
```
When the pipeline finishes, as soon as Nu sees a value that is of type row it will try to display it as a table with columns. The reason is that a value of type row represents rows having column cell headers and cell values.
We appended the value 10 using `append`. Nu sees **four** values in the stream, **three** of them being row types and **one** being an int value type. Therefore we see a table printed (the three row values) and a list (one int value) from the **stream**. This matters because some commands expect and assume all values coming in are row types and some do not.
For the command `take-two` we are about to implement we don't care what kind of values are coming in since we just want to **take two** values.
## Command implementation steps
To guide us in our command implementation journey we will start registering the command, as we do so we will be driving out the command.
### Register the command
All the internal commands reside in `crates/nu-command`. For our command named `take-two` we can create the source file `take_two.rs` and place it in `src/commands/take_two.rs`. Go ahead and create it:
```
> touch crates/nu-command/src/commands/take_two.rs
```
Edit the source file and add the following:
```rust
pub struct Command;
```
Before registering it to the context you need to make it available by declaring the module and re-export it in `crates/nu-command/src/commands.rs`. The commands we write are modules already (`take_two.rs` is the `take_two` module). In case you are not familiar with rust modules [read this refresher](https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html). Let's go ahead and declare it and then re-export the command's `Command` struct as `TakeTwo`, like so:
_nu-command/src/mod.rs_
```rust
# ...
pub(crate) mod take_two;
# ...
# ...
pub(crate) use take_two::Command as TakeTwo;
# ...
```
We should be ready now to register it. You need to add the command (in this case the struct will be in scope named as `TakeTwo` from the previous snippet) where they are added one by one to the context.
_src/commands/default_context.rs_
```rust
context.add_commands(vec![
# ...
whole_stream_command(TakeTwo),
# ...
);
```
We will now resort to the rust compiler to make sure things are wired up correctly. Under `crates/nu-command` run:
```
> cargo build
Compiling nu-command v0.29.2 (/Users/nu/nushell/crates/nu-command)
error[E0277]: the trait bound `take_two::Command: nu_engine::WholeStreamCommand` is not satisfied
--> crates/nu-command/src/commands/default_context.rs:13:34
|
13 | whole_stream_command(TakeTwo),
| ^^^^^^^ the trait `nu_engine::WholeStreamCommand` is not implemented for `take_two::Command`
|
::: /Users/nu/nushell/crates/nu-engine/src/whole_stream_command.rs:273:43
|
273 | pub fn whole_stream_command(command: impl WholeStreamCommand + 'static) -> Command {
| ------------------ required by this bound in `whole_stream_command`
error[E0277]: the trait bound `take_two::Command: nu_engine::WholeStreamCommand` is not satisfied
--> crates/nu-command/src/commands/default_context.rs:13:34
|
13 | whole_stream_command(TakeTwo),
| ^^^^^^^ the trait `nu_engine::WholeStreamCommand` is not implemented for `take_two::Command`
|
::: /Users/nu/nushell/crates/nu-engine/src/whole_stream_command.rs:273:43
|
273 | pub fn whole_stream_command(command: impl WholeStreamCommand + 'static) -> Command {
| ------------------ required by this bound in `whole_stream_command`
error: aborting due to previous error
```
That's not certainly what we expected.
It happens that Nu needs to know more about the command, including it's name and signature. We didn't do any of that and the compiler is telling us so. We seem to be missing implementing the `WholeStreamCommand` trait. This is the trait that, when implemented, allows us to state it's name, signature, and the like.
## WholeStreamCommand
Every internal command must implement the `WholeStreamCommand` trait. Let's take a look at the required functions:
```rust
pub trait WholeStreamCommand: Send + Sync {
fn name(&self) -> &str;
fn signature(&self) -> Signature;
fn usage(&self) -> &str;
}
```
_Note: For simplicity, we've removed the default implementations of the trait. If you want to read more about the trait you [can read the code here](https://github.com/nushell/nushell/blob/e09e3b01d6523309b901fb396b416146b53c2b7f/crates/nu-engine/src/whole_stream_command.rs)_
We will need to implement the required functions `name` for telling Nu the name of the command, `signature` to tell the command's signature, and `usage`. Before we start, we will also write an example of the usage implementing `examples` (not shown above).
Ready? Go ahead and edit `crates/nu-command/src/commands/take_two.rs`:
```rust
use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_protocol::Signature;
pub struct Command;
impl WholeStreamCommand for Command {
fn name(&self) -> &str {
"take-two"
}
fn usage(&self) -> &str {
"takes two values"
}
fn signature(&self) -> Signature {
Signature::build("take-two")
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Takes two values",
example: "echo [11161984 500 200] | take-two",
result: None,
},
]
}
}
```
Let's try again by running `cargo build`:
```
cargo build
Compiling nu-command v0.29.2 (/Users/nu/nushell/crates/nu-command)
Finished dev [unoptimized + debuginfo] target(s) in 10.56s
```
Great!
Since we have been working in `crates/nu-command` and building there to shorten the build time as we work on the command, you may want to run a full build now by doing `cargo build --all --features=extra`:
Let's try entering `help take-two`:
```
> help take-two
takes two values
Usage:
> take-two {flags}
Flags:
-h, --help: Display this help message
Examples:
Takes two values
> echo [11161984 500 200] | take-two
```
We get a help description of our newly implemented `take-two` command for free. This works because we implemented `examples`. It's good practice to do so for documentation (and as we will soon see, unit testing) purposes.
Now let's run `echo [11161984 500 200] | take-two`
```
> echo [11161984 500 200] | take-two
error: Error: Unimplemented: take-two does not implement run or run_with_actions
```
That was unexpected. What happened?
We did not implement `take-two`'s logic anywhere. Nu is telling us the command does not implement `run` or `run_with_actions`. These functions are in the `WholeStreamCommand` trait and the default implementation gives the error. Since our command won't be doing any actions we can go ahead and implement `run` for the logic, let's do that:
```rust
use nu_errors::ShellError;
# ...
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(args.input.take(2).into_output_stream())
}
# ...
```
Compile and try one more time:
```
> echo [11161984 500 200] | take-two
───┬──────────
0 │ 11161984
1 │ 500
───┴──────────
```
Not bad. We created first a list of int values and took two of them. Let's create row type values and take two of them now:
```
> echo [[LOC]; [11161984] [500] [200]] | take-two
───┬──────────
# │ LOC
───┼──────────
0 │ 11161984
1 │ 500
───┴──────────
```
The command is ready.