суббота, мая 19, 2012

Keeping known_hosts clean

I've recently was cleaning up stuff on my laptop and ~/.ssh/known_hosts got my attention. >100 records. Do I actually need them? I've went through the file and deleted all IP hosts. I do not remember what those hosts are for and if so it is ok with me to remove them.
Some hosts had both domain name and IP address:
foo.example.com,12.34.45.67  ssh-rsa ...
If I reference host with domain name, I do not want to track it's IP address. It's their own business. So I left only domain name for such hosts.
Also, it is ok to leave comments (starting with "#" mark) and blank lines in known_hosts file, so I grouped hosts, added comments and make it pretty.
Then I decided to test how it works. Connected to one of hosts that is referenced with a hostname in my known_hosts, and noticed that SSH put an extra record for that IP address. What? Again?

Googling showed that it following SSH option can help:
  "CheckHostIP no"  - I don't care about DNS spoofing as long as they key is valid.

CheckHostIP can be also handy in situation when you have host with dynamic IP and dynamic DNS entry. In this case you will get additional known_hosts file entry when you access this host and it's IP address have changed. To workaround this, you can set CheckHostIP option to this host only. In ~/.ssh/config write:

Host dynamic.example.com
CheckHostIP no

 

вторник, мая 18, 2010

Test until pass

"Test until pass" is this week one-liner.

вторник, февраля 02, 2010

Do you use LiveJournal ?

Every time I visit someone's page on LiveJournal, I see something like this.

It reminds me a Homer Simpson's web page. How people can use that crap ? Duh.

понедельник, сентября 14, 2009

Building tree out of nested set


This keeps popping up over and over again. About 2 years ago I mentioned solution on how to build tree out of nested set, but the solution was lost in google groups. I'm going to publish it here.

So, nested set: every item has LEFT and RIGHT numbers. LEFT number is less than any LEFT or RIGHT number of any descendant item. RIGHT number is greater than any LEFT or RIGHT number of any descendant item. To get a subtree, select all items with LEFT greater than given LEFT and RIGHT less than given RIGHT number. You get the flat array of items of that tree structure. Next thing is to convert it to tree which means for any given item you need the ability to iterate over all of it's children.

First thing you need to do is to order items by LEFT number, than by RIGHT number.

A small sidenote: we will assume that LEFT and RIGHT numbers are compact so that if your root item has LEFT=1 and RIGHT=10 then for each number X in interval [1, 10] there is item for which X is the value of LEFT or RIGHT. This allows easy calculation of how many descendants particular item has.

So, say we have an flat array and we need to know how many items in array you need to skip to get to given item's next sibling. And that number is (RIGHT-LEFT) (minus one if you do not count the item itself).
# Class that allows performance wise traversing a list of items
# that form a part of nested set structure.
class NestedSetTreePresenter
  include Enumerable

  # Constructs presenter with a items that form part of nested set,
  # offset of first item on desired level and count - number of items
  # on current level.
  # Items should be ordered by their left bound values.
  def initialize(items, offset = 0, count = nil)
    @items = items
    @offset = offset
    @count = count || @items.size
  end

  # For each item of the same level in nested set as the first item
  # calls block passing corresponding item.
  def each
    i = @offset
    bound = @offset + @count
    bound = @items.size if bound > @items.size

    while i<bound
      item = @items[i]
      descendants_count = (item.rgt-item.lft)/2
      yield item
      i += 1 + descendants_count
    end
  end

  # For each item of the same level in nested set as the first item
  # calls block passing corresponding item and collection, that
  # represent all immediate children of that item. Collection is also
  # an instance of this class.
  def each_with_children
    i = @offset
    bound = @offset + @count
    bound = @items.size if bound > @items.size

    while i<bound
      item = @items[i]
      descendants_count = (item.rgt-item.lft)/2
      yield item, NestedSetTreePresenter.new(@items, i+1, descendants_count)
      i += 1 + descendants_count
    end
  end
end
I chose not to yield a proxy, container or anything else to minimize the number of objects created.

Here is how to use it:
def print_tree(items, level = 0)
  items.each_with_children do |item, children|
    puts "  "*level + item.name
    print_tree(children, level+1)
  end
end

print_tree(NestedSetTreePresenter.new(items))

вторник, августа 25, 2009

RSpec's matchers without all bullshit

I've used to use and like RSpec. The problem was that it always broke with new versions of Rails and internals were too complex to understand. Then appeared Shoulda and removed the pain of writing RUnit tests, so I switched to using it. But I always missed the elegance of RSpec's matchers.

Until Matchy appeared.

The cool thing about it is that you can create custom matchers easily with #custom_matcher() method provided. Nice.